{ : G make } Where Define (make MAP) Let compare MAP.compare Let SET (SEARCH.SET MAP.compare) In Define (traverse g adj i stack preorder assigned components) Define (rec rec adj i stack preorder assigned components) Let {v neighbors} adj In Let preorder (MAP.insert preorder {v i}) Let stack [v & stack] In Let {link j 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 (Z.min link j) In {link i stack preorder assigned components} | 'nothing Let adj Match (MAP.search g w) | 'nothing {w 'nil} | 'just.adj adj ; In Let {link_rec i stack preorder assigned components} (rec rec adj i stack preorder assigned components) In Let link (Z.min link link_rec) In {link i stack preorder assigned components} ; ;) In If [i = link] Block Let {c stack assigned} Iterate {c stack assigned} From {'nil 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 j stack preorder assigned [c & components]} {link j stack preorder assigned components} In (rec rec adj i stack preorder assigned components) In Define (strongly_connected_components g) Iterate {adjs i stack preorder assigned components} From {(MAP.list g) 0 'nil MAP.empty SET.empty 'nil} Match adjs | 'nil (LIST.reverse components) | 'cons.{adj adjs} Let {v _} adj In Match (SET.search assigned v) | 'just._ Continue {adjs i stack preorder assigned components} | 'nothing Let {link i stack preorder assigned components} (traverse g adj i stack preorder assigned components) In Continue {adjs i stack preorder assigned components} ; ; In Define (layers g) Iterate {layers adjs} From {'nil (MAP.list g)} Let {layer adjs} (LIST.fold adjs {'nil 'nil} 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 { : 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" Let Z Package "z"