fork download
  1. module Main where
  2.  
  3. import Control.Monad.Identity
  4. import Control.Arrow (second)
  5. import Text.Parsec
  6.  
  7. data Term = Var String
  8. | Idx Int
  9. | Abs Term
  10. | App Term Term
  11.  
  12. avnames = map (\x -> [x]) "abcdexyzuw"
  13. names = avnames ++ map ('\'' :) names
  14.  
  15. nameidx i n (Abs t) = Abs (nameidx (i + 1) n t)
  16. nameidx i n (App x y) = App (nameidx i n x) (nameidx i n y)
  17. nameidx i n (Idx d)
  18. | i == d = Var n
  19. | otherwise = Idx d
  20. nameidx _ _ v = v
  21.  
  22. markfree (Abs t) = Abs (markfree t)
  23. markfree (App x y) = App (markfree x) (markfree y)
  24. markfree (Var s) = Var ('*' : s)
  25. markfree i = i
  26.  
  27. showTerm :: [String] -> Term -> ShowS
  28. showTerm (n:ns) (Abs t) =
  29. showString "(\\"
  30. . showString ". "
  31. . showTerm ns (nameidx 0 n t)
  32. . showString ")"
  33. showTerm ns (App x y) =
  34. . showTerm ns x
  35. . showChar ' '
  36. . showTerm ns y
  37. . showChar ')'
  38. showTerm ns (Idx i) = ('#' :) . (show i ++)
  39. showTerm ns (Var s) = (s ++)
  40.  
  41. instance Show Term where
  42. show t = showTerm names (markfree t) $ []
  43.  
  44. type Eval a = Identity a
  45.  
  46. runEval :: Eval Term -> Term
  47. runEval = runIdentity
  48.  
  49. eval :: Term -> Eval Term
  50. eval (App x y) = do
  51. x' <- eval x
  52. case x' of
  53. (Abs t) -> eval (subst 0 t y)
  54. proc -> return (App proc y)
  55. eval other = return other
  56.  
  57. subst :: Int -> Term -> Term -> Term
  58. subst i (Idx d) s
  59. | d == i = s
  60. | otherwise = Idx d
  61. subst i (App x y) s = App (subst i x s) (subst i y s)
  62. subst i (Abs t) s = Abs (subst (i + 1) t s)
  63. subst i v s = v
  64.  
  65. setidx :: String -> Int -> Term -> Term
  66. setidx name i (App x y) = App (setidx name i x) (setidx name i y)
  67. setidx name i (Abs t) = Abs (setidx name (i + 1) t)
  68. setidx name i (Var n)
  69. | name == n = Idx i
  70. | otherwise = Var n
  71. setidx _ _ t = t
  72.  
  73. setVariable :: Term -> (String, Term) -> Term
  74. setVariable (App x y) bind =
  75. App (setVariable x bind) (setVariable y bind)
  76. setVariable (Abs t) bind = Abs (setVariable t bind)
  77. setVariable (Var s) (name, t')
  78. | s == name = t'
  79. | otherwise = Var s
  80. setVariable other _ = other
  81.  
  82. identifier :: Parsec String () String
  83. identifier = many1 alphaNum
  84.  
  85. lambda :: Parsec String () Term
  86. lambda = do
  87. char '('
  88. char '\\'
  89. spaces
  90. varname <- identifier
  91. spaces
  92. char '.'
  93. t <- term
  94. char ')'
  95. return $ Abs (setidx varname 0 t)
  96.  
  97. single :: Parsec String () Term
  98. single = (spaces >>) $ try (fmap Var identifier) <|> try lambda <|> application
  99.  
  100. application :: Parsec String () Term
  101. application = do
  102. char '('
  103. f <- term
  104. char ')'
  105.  
  106. substitution :: Parsec String () (String, Term)
  107. substitution = do
  108. spaces
  109. char '['
  110. spaces
  111. varname <- identifier
  112. spaces
  113. string "->"
  114. t <- term
  115. char ']'
  116. return (varname, t)
  117.  
  118. procBinds :: [(String, Term)] -> [(String, Term)]
  119. procBinds = scanl1 $ \x -> second (flip setVariable x)
  120.  
  121. term :: Parsec String () Term
  122. term = do
  123. spaces
  124. binds <- many (try substitution)
  125. t <- try (fmap (foldl1 App) (many1 single))
  126. return (foldl (setVariable) t $ procBinds binds)
  127.  
  128. lambdaEval str =
  129. case parse term "lambda" str of
  130. Right t -> Right $ runEval (eval t)
  131. Left e -> Left e
  132.  
  133. loop :: IO ()
  134. loop = do
  135. x <- getLine
  136. case x of
  137. ":end" -> return ()
  138. str -> putStr "> " >> print (lambdaEval x) >> loop
  139.  
  140. main :: IO ()
  141. main = do
  142. putStrLn "Lambda-Expressions Evaluator.\n> "
  143. loop
Not running #stdin #stdout 0s 0KB
stdin
Standard input is empty
stdout
Standard output is empty