~/ ~/documents ~/recommended-reading ~/software ~/pictures github (opens in new tab)

Boiled Egg

Deterministic boiled egg. Cold egg direct from refrigeration (4°C) into boiling water (100°C).

Inputs

  • 1 large egg (approx. 60g, refrigerated)
  • Water: sufficient volume to submerge egg with 25mm clearance
  • Ice water bath: 50/50 ice and tap water

Execution

  1. Bring water to a vigorous rolling boil.
  2. Pierce the air cell at the blunt end using a pin to relieve internal pressure.
  3. Lower egg directly into the boil on a slotted spoon. Reduce heat slightly to prevent shell fracture against the pan.
  4. Timer begins on immersion:
    • 6m 00s: Jammy yolk, fully set white.
    • 7m 30s: Warm custardy center.
    • 10m 00s: Hard set, zero grey ring.
  5. Plunge immediately into the ice bath for 180 seconds to arrest cooking.
  6. Peel submerged or under cold running water starting from the blunt end.
module BoiledEgg where

data Firmness = Soft | Medium | Hard deriving (Show, Eq)

data Raw = Raw deriving (Show)
data Pricked = Pricked deriving (Show)
data Boiled = Boiled Firmness deriving (Show)
data Chilled = Chilled Firmness deriving (Show)
data Peeled = Peeled Firmness deriving (Show)

newtype Egg state = Egg state deriving (Show)

data ColdWater = ColdWater deriving (Show)
data RollingBoil = RollingBoil deriving (Show)
data GentleBoil = GentleBoil deriving (Show)
data IceBath = IceBath deriving (Show)

boilWater :: ColdWater -> RollingBoil
boilWater ColdWater = RollingBoil

prick :: Egg Raw -> Egg Pricked
prick (Egg Raw) = Egg Pricked

reduceHeat :: RollingBoil -> GentleBoil
reduceHeat RollingBoil = GentleBoil

cook :: Firmness -> Egg Pricked -> GentleBoil -> Egg Boiled
cook firmness (Egg Pricked) GentleBoil = Egg (Boiled firmness)

chill :: Egg Boiled -> IceBath -> Egg Chilled
chill (Egg (Boiled f)) IceBath = Egg (Chilled f)

peel :: Egg Chilled -> Egg Peeled
peel (Egg (Chilled f)) = Egg (Peeled f)

makeBoiledEgg :: Firmness -> Egg Raw -> ColdWater -> IceBath -> Egg Peeled
makeBoiledEgg firmness rawEgg coldWater iceBath =
    let rollingBoil = boilWater coldWater
        gentleBoil  = reduceHeat rollingBoil
        prickedEgg  = prick rawEgg
        boiledEgg   = cook firmness prickedEgg gentleBoil
        chilledEgg  = chill boiledEgg iceBath
    in peel chilledEgg

Let the boiling process be modeled as a sequence of typed state transformations given parameters f∈Firmnessf \in \text{Firmness}, w∈ColdWaterw \in \text{ColdWater}, and i∈IceBathi \in \text{IceBath}:

prick:EggRaw→EggPrickedcookf,b:EggPricked→EggBoiledchilli:EggBoiled→EggChilledpeel:EggChilled→EggPeeledboilWater:ColdWater→RollingBoilreduceHeat:RollingBoil→GentleBoil \begin{array}{l} \text{prick} : \text{Egg}_{\text{Raw}} \rightarrow \text{Egg}_{\text{Pricked}} \\ \text{cook}_{f,b} : \text{Egg}_{\text{Pricked}} \rightarrow \text{Egg}_{\text{Boiled}} \\ \text{chill}_i : \text{Egg}_{\text{Boiled}} \rightarrow \text{Egg}_{\text{Chilled}} \\ \text{peel} : \text{Egg}_{\text{Chilled}} \rightarrow \text{Egg}_{\text{Peeled}} \\[0.5em] \text{boilWater} : \text{ColdWater} \rightarrow \text{RollingBoil} \\ \text{reduceHeat} : \text{RollingBoil} \rightarrow \text{GentleBoil} \end{array}

where parameters and heat preparation bb are specified by:

f∈Firmness={Soft,Medium,Hard},w∈ColdWater,i∈IceBathf \in \text{Firmness} = \{ \text{Soft}, \text{Medium}, \text{Hard} \}, \quad w \in \text{ColdWater}, \quad i \in \text{IceBath}

t(Soft)=360s(6m),t(Medium)=450s(7.5m),t(Hard)=600s(10m)t(\text{Soft}) = 360\,\text{s}\;(6\text{m}), \quad t(\text{Medium}) = 450\,\text{s}\;(7.5\text{m}), \quad t(\text{Hard}) = 600\,\text{s}\;(10\text{m})

b=reduceHeat∘boilWater:ColdWater→GentleBoilb = \text{reduceHeat} \circ \text{boilWater} : \text{ColdWater} \to \text{GentleBoil}

The composite transformation makeBoiledEggf,w,i\text{makeBoiledEgg}_{f,w,i} is defined by function composition:

makeBoiledEggf,w,i=peel∘chilli∘cookf,b(w)∘prick:EggRaw→EggPeeled\text{makeBoiledEgg}_{f,w,i} = \text{peel} \circ \text{chill}_i \circ \text{cook}_{f,b(w)} \circ \text{prick} : \text{Egg}_{\text{Raw}} \to \text{Egg}_{\text{Peeled}}

The commutative diagram below illustrates the sequential state pipeline:

graph TD
    R["Egg Raw"] -->|"prick"| P["Egg Pricked"]
    P -->|"cook with f and b(w)"| B["Egg Boiled"]
    B -->|"chill in i"| C["Egg Chilled"]
    C -->|"peel"| E["Egg Peeled"]
    R -.->|"makeBoiledEgg with f, w, i"| E