diff --git a/rlp.cabal b/rlp.cabal index 5880571..c1bedaa 100644 --- a/rlp.cabal +++ b/rlp.cabal @@ -28,13 +28,13 @@ library , Core.Utils , Core.TH , Core.HindleyMilner + , Control.Monad.Errorful other-modules: Data.Heap , Data.Pretty , Core.Parse , Core.Lex , Core2Core - , Control.Monad.Errorful , Control.Monad.Utils , RLP.Syntax diff --git a/tst/Core/HindleyMilnerSpec.hs b/tst/Core/HindleyMilnerSpec.hs index 07940e6..8f498a9 100644 --- a/tst/Core/HindleyMilnerSpec.hs +++ b/tst/Core/HindleyMilnerSpec.hs @@ -6,7 +6,8 @@ module Core.HindleyMilnerSpec ---------------------------------------------------------------------------------- import Core.Syntax import Core.TH (coreExpr) -import Core.HindleyMilner (infer, check, TypeError(..), HMError) +import Core.HindleyMilner +import Control.Monad.Errorful import Data.Either (isLeft) import Test.Hspec ---------------------------------------------------------------------------------- @@ -16,24 +17,30 @@ spec :: Spec spec = do it "should infer `id 3` :: Int" $ let g = [ ("id", "a" :-> "a") ] - in infer g [coreExpr|id 3|] `shouldBe` Right TyInt + in infer' g [coreExpr|id 3|] `shouldBe` Right TyInt it "should not infer `id 3` when `id` is specialised to `a -> a`" $ let g = [ ("id", ("a" :-> "a") :-> "a" :-> "a") ] - in infer g [coreExpr|id 3|] `shouldSatisfy` isLeft + in infer' g [coreExpr|id 3|] `shouldSatisfy` isLeft -- TODO: property-based tests for let it "should infer `let x = 3 in id x` :: Int" $ let g = [ ("id", "a" :-> "a") ] e = [coreExpr|let {x = 3} in id x|] - in infer g e `shouldBe` Right TyInt + in infer' g e `shouldBe` Right TyInt it "should infer `let x = 3; y = 2 in (+#) x y` :: Int" $ let g = [ ("+#", TyInt :-> TyInt :-> TyInt) ] e = [coreExpr|let {x=3;y=2} in (+#) x y|] - in infer g e `shouldBe` Right TyInt + in infer' g e `shouldBe` Right TyInt it "should find `3 :: Bool` contradictory" $ let e = [coreExpr|3|] - in check [] (TyCon "Bool") e `shouldSatisfy` isLeft + in check' [] (TyCon "Bool") e `shouldSatisfy` isLeft + +infer' :: Context' -> Expr' -> Either TypeError Type +infer' g e = fmap fst . runErrorful $ infer g e + +check' :: Context' -> Type -> Expr' -> Either TypeError () +check' g t e = fmap fst . runErrorful $ check g t e