import Text.Parsec main :: IO () main = mapM_ (parseTest assign) $ [ "id = \\ x -> x" , "const = \\ x y -> x" , "skip = \\ x y -> y" , "flip = \\ f x y -> f y x" , "compose = \\ f g a -> f (g a)" , "apply = \\ a f -> f a" , "fix = \\ f -> (\\ x -> f (x x)) (\\ x -> f (x x))" ] type Name = String data Expr = Var Name | Lam Name Expr | App Expr Expr deriving (Show, Eq) name = (do c <- letter <|> char '_' cs <- many (letter <|> digit <|> oneOf "'_") return (c:cs) ) "name" var = (Var <$> name) "var" lam = (do ns <- char '\\' *> spaces *> sepEndBy1 name spaces e <- string "->" *> spaces *> expr (return (foldl1 (.) (fmap Lam ns) e)) ) "lam" paren = between (char '(' *> spaces) (char ')' *> spaces) nonApp = (paren expr <|> lam <|> var) "non-app expr" expr = chainl1 (nonApp <* spaces) (pure App) "expr" assign = do n <- name <* spaces char '=' <* spaces e <- expr return (n,e)