summaryrefslogtreecommitdiff
path: root/lambda-calcul/haskell/test/Minilang/Lambda/EvalSpec.hs
diff options
context:
space:
mode:
Diffstat (limited to 'lambda-calcul/haskell/test/Minilang/Lambda/EvalSpec.hs')
-rw-r--r--lambda-calcul/haskell/test/Minilang/Lambda/EvalSpec.hs112
1 files changed, 70 insertions, 42 deletions
diff --git a/lambda-calcul/haskell/test/Minilang/Lambda/EvalSpec.hs b/lambda-calcul/haskell/test/Minilang/Lambda/EvalSpec.hs
index 3dbe3cd..d772fe0 100644
--- a/lambda-calcul/haskell/test/Minilang/Lambda/EvalSpec.hs
+++ b/lambda-calcul/haskell/test/Minilang/Lambda/EvalSpec.hs
@@ -2,52 +2,80 @@ module Minilang.Lambda.EvalSpec (spec) where
import Control.Concurrent (threadDelay)
import Control.Concurrent.Async (race_)
-import Minilang.Lambda.Eval (Term (..), eval)
+import Minilang.Lambda.Eval (Term (..), Value, eval, normalise)
import Test.Hspec (Spec, describe, it, pending, shouldBe)
spec :: Spec
-spec = it "evaluates Term" pending
+spec = do
+ let y =
+ Lam
+ "f"
+ ( App
+ (Lam "x" (App (Var "f") (App (Var "x") (Var "x"))))
+ (Lam "x" (App (Var "f") (App (Var "x") (Var "x"))))
+ )
+ z =
+ Lam
+ "f"
+ ( App
+ (Lam "x" (App (Var "f") (Lam "y" (App (App (Var "x") (Var "x")) (Var "y")))))
+ (Lam "x" (App (Var "f") (Lam "y" (App (App (Var "x") (Var "x")) (Var "y")))))
+ )
--- let fix =
--- Lam
--- "f"
--- ( App
--- (Lam "x" (App (Var "f") (App (Var "x") (Var "x"))))
--- (Lam "x" (App (Var "f") (App (Var "x") (Var "x"))))
--- )
--- let omega = App fix fix
--- let term = App (App (Lam "x" (Lam "y" (Var "y"))) omega) (Var "z")
--- let fst' = Lam "x" (Lam "y" (Var "x"))
+ omega =
+ App (Lam "x" (App (Var "x") (Var "x"))) (Lam "x" (App (Var "x") (Var "x")))
--- describe "call-by-value eval" $ do
--- it "evaluates 'x' as itself" $ do
--- let term = Var "x"
--- eval term [] `shouldBe` V "x"
--- it "evaluates '((λ x. x) y)' as 'y'" $ do
--- let term = App (Lam "x" (Var "x")) (Var "y")
--- eval term [] `shouldBe` V "y"
--- it "evaluates '((λ x y. y) z t y)' as '(t y)'" $ do
--- let snd' = Lam "x" (Lam "y" (Var "y"))
--- let term = App (App (App snd' (Var "z")) (Var "t")) (Var "y")
--- eval term [] `shouldBe` Ap (V "t") (V "y")
--- it "evaluates '((λ x y. x) z t)' as 'z'" $ do
--- let term = App (App fst' (Var "z")) (Var "t")
--- eval term [] `shouldBe` V "z"
--- it "diverges on evaluating argument bound to ω" $
--- shouldDiverge $
--- eval term []
+ fst' = Lam "x" (Lam "y" (Var "x"))
+ snd' = Lam "x" (Lam "y" (Var "y"))
--- describe "call-by-need eval" $ do
--- it "evaluates 'x' as itself" $ do
--- evalNeed (Var "x") [] `shouldBe` V "x"
--- it "evaluates '(λ x y . y) ⊥ z' as 'z'" $ do
--- evalNeed term [] `shouldBe` V "z"
--- it "diverges on evaluating ω" $
--- shouldDiverge $
--- evalNeed omega []
+ describe "call-by-value eval" $ do
+ it "evaluates 'x' as itself" $ do
+ let term = Var "x"
+ normalise term `shouldBe` Var "x"
+ it "evaluates '((λ x. x) y)' as 'y'" $ do
+ let term = App (Lam "x" (Var "x")) (Var "y")
+ normalise term `shouldBe` Var "y"
+ it "evaluates '((λ x y. y) z t y)' as '(t y)'" $ do
+ let term = App (App (App snd' (Var "z")) (Var "t")) (Var "y")
+ normalise term `shouldBe` App (Var "t") (Var "y")
+ it "evaluates '((λ x y. x) z t)' as 'z'" $ do
+ let term = App (App fst' (Var "z")) (Var "t")
+ normalise term `shouldBe` Var "z"
+ it "diverges on evaluating ω" $
+ shouldDiverge $
+ normalise omega
+ it "diverges on evaluating ω applied to a function that use it" $
+ shouldDiverge $
+ normalise (App fst' omega)
+ it "diverges on evaluating ω applied to a function that do not use it" $
+ shouldDiverge $
+ normalise (App snd' omega)
+ describe "Church numerals" $ do
+ let zero = Lam "s" (Lam "z" (Var "z"))
+ one = Lam "s" (Lam "z" (App (Var "s") (Var "z")))
+ two = Lam "s" (Lam "z" (App "s" (App (Var "s") (Var "z"))))
+ succ' = Lam "n" (Lam "s" (Lam "z" (App (Var "s") (App (App (Var "n") (Var "s")) (Var "z")))))
+ add' = Lam "j" (Lam "k" (Lam "s" (Lam "z" (App (App "j" "s") (App (App "k" "s") "z")))))
--- shouldDiverge :: Value -> IO ()
--- shouldDiverge t =
--- race_
--- (t `seq` fail "Did not diverge")
--- (threadDelay 1000000)
+ it "normalises successor" $
+ normalise (App succ' zero)
+ `shouldBe` one
+
+ it "adds two numerals" $
+ normalise (App (App add' one) one)
+ `shouldBe` two
+
+ -- describe "call-by-name eval" $ do
+ -- it "evaluates 'x' as itself" $ do
+ -- normalise' (Var "x") `shouldBe` Var "x"
+ -- it "evaluates '(λ x y . y) ⊥ z' as 'z'" $ do
+ -- normalise' (App (App snd' omega) "z") `shouldBe` Var "z"
+ -- it "diverges on evaluating ω" $
+ -- shouldDiverge $
+ -- normalise' omega
+
+shouldDiverge :: Term -> IO ()
+shouldDiverge t =
+ race_
+ (t `seq` fail "Did not diverge")
+ (threadDelay 1000000)