{Record G:make} Where Let (make MAP) Let compare MAP.compare In Let ADJ {Record vertex:Func item. item.0 neighbors:Func item. item.1} Let SET (SEARCH.SET compare) In Let (min a b) If (a < b) a b In Define (traverse g adj i stack preorder assigned components) Let v (ADJ.vertex adj) Let neighbors (ADJ.neighbors adj) In Let preorder (MAP.insert preorder {v i}) Let stack (v :: stack) In Let {link i' stack preorder assigned components} (LIST.reduce neighbors {i (i + 1) stack preorder assigned components} Func state w. Let {link i stack preorder assigned components} state In Match (SET.search assigned w) | `just._ state | `nothing Match (MAP.search preorder w) | `just.{_ j} Let link (min link j) In {link i stack preorder assigned components} | `nothing Let adj Match (MAP.search g w) | `nothing {w []} | `just.adj adj ; In Let {link' i stack preorder assigned components} (traverse g adj i stack preorder assigned components) In Let link (min link link') In {link i stack preorder assigned components} ; ;) In If (i = link) Block Let {c stack assigned} Iterate {c stack assigned} From {[] stack assigned} Match stack | `cons.{w stack} Let assigned (SET.insert assigned w) In Match (compare w v) | `equal {(v :: c) stack assigned} | _ Continue {(w :: c) stack assigned} ; ; In {link i' stack preorder assigned (c :: components)} {link i' stack preorder assigned components} In Let (strongly_connected_components g) Iterate {g adjs i stack preorder assigned components} From {g (MAP.list g) 0 [] MAP.empty SET.empty []} Match adjs | `nil (LIST.reverse components) | `cons.{adj adjs} Match (SET.search assigned (ADJ.vertex adj)) | `just._ Continue {g adjs i stack preorder assigned components} | `nothing Let {link i stack preorder assigned components} (traverse g adj i stack preorder assigned components) In Continue {g adjs i stack preorder assigned components} ; ; In Let (layers g) Iterate {layers adjs} From {[] (MAP.list g)} Let {layer adjs} (LIST.fold adjs {[] []} Func {v neighbors} {layer adjs}. Match neighbors | `nil {(v :: layer) adjs} | `cons._ {layer ({v neighbors} :: adjs)} ;) In Match layer | `nil layers | `cons._ Let removed (LIST.reduce layer SET.empty SET.insert) In Let adjs (LIST.map adjs Func {v neighbors}. Let neighbors (SET.list (SET.diff (SET.new neighbors) removed)) In {v neighbors}) In Continue {(layer :: layers) adjs} ; In {Record strongly_connected_components layers} Where Let die OS.die Where Let LIST Package "list" Let OS Package "os" Let SEARCH Package "search" Let STDIO Package "stdio"