-- See Simon L. Peyton Jones and David R. Lester, "Implementing Functional -- Languages: a tutorial", section 6.8. undefined = undefined; data Bool = True | False; id x = x; (.) f g = \x -> f (g x); flip f = \x y -> f y x; (==) x y = case x <= y of { True -> y <= x ; False -> x <= y }; ife b t f = case b of { True -> t ; False -> f }; foldr c n xs = case xs of { [] -> n ; (:) h t -> c h (foldr c n t) }; foldl f a bs = foldr (\b g x -> g (f x b)) id bs a; foldl1 f xs = case xs of { [] -> undefined ; (:) h t -> foldl f h t }; map = flip (foldr . ((.) (:))) []; (++) = \xs ys -> foldr (:) ys xs; concat = foldr (++) []; concatMap = (concat .) . map; elemWith f k xs = foldr (\x t -> ife (f x k) True t) False xs; elem = elemWith (==); eqStr s t = case s of { [] -> case t of { [] -> True; (:) _ _ -> False } ; (:) x xs -> case t of { [] -> False ; (:) y ys -> ife (x == y) (eqStr xs ys) False } }; elemStr = elemWith eqStr; data Maybe a = Nothing | Just a; lookup n = foldr (\h t -> case h of { Pair k v -> ife (n == k) (Just v) t }) Nothing; data Pair x y = Pair x y; fst p = case p of { Pair x _ -> x }; snd p = case p of { Pair _ y -> y }; break p xs = case xs of { [] -> Pair [] [] ; (:) x xs' -> ife (p x) (Pair [] xs) (case break p xs' of { Pair ys zs -> Pair (x:ys) zs }) }; lines s = case s of { [] -> [] ; (:) _ _ -> case break (\c -> '\n' == c) s of { Pair l s' -> l : case s' of { [] -> [] ; (:) _ s'' -> lines s'' } } }; dropWhile p xs = case xs of { [] -> [] ; (:) x xs' -> ife (p x) (dropWhile p xs') xs }; length xs = case xs of { [] -> 0 ; (:) x xt -> 1 + length xt }; isSpace c = c `elem` " \n"; words s = case dropWhile isSpace s of { [] -> [] ; (:) h t -> case break isSpace (h:t) of { Pair w s' -> w:words s' } }; unwords xs = case xs of { [] -> "" ; (:) x xt -> x ++ foldr (\a s -> ' ':a ++ s) "" xt }; depthFirstSearch = let { search relation st vertex = case st of { Pair visited sequence -> ife (vertex `elemStr` visited) st (case depthFirstSearch relation (Pair (vertex:visited) sequence) (relation vertex) of { Pair visited' sequence' -> Pair visited' (vertex:sequence') }) } } in foldl . search; spanningSearch = let { search relation st vertex = case st of { Pair visited setSequence -> ife (vertex `elemStr` visited) st (case depthFirstSearch relation (Pair (vertex:visited) []) (relation vertex) of { Pair visited' sequence -> Pair visited' ((vertex:sequence):setSequence) }) } } in foldl . search; scc ins outs = let { depthFirst = snd . depthFirstSearch outs (Pair [] []) ; spanning = snd . spanningSearch ins (Pair [] []) } in spanning . depthFirst; go s = let { nums = map words (lines s) ; outs v = foldr (\h t -> case h of { [] -> t ; (:) x xs -> ife (x `eqStr` v) xs t }) [] nums ; ins w = foldr (\h t -> case h of { [] -> t ; (:) x xs -> ife (w `elemStr` xs) (x:t) t }) [] nums } in concatMap (++ "\n") (map unwords (scc ins outs (concat nums)));