-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1601b02
commit 0003f18
Showing
9 changed files
with
180 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
module Elara.TypeInfer.Ftv where | ||
|
||
import Data.Set (difference, member) | ||
import Elara.TypeInfer.Type (Monotype (..), Type (..)) | ||
import Elara.TypeInfer.Unique | ||
|
||
class Ftv a where | ||
ftv :: a -> Set UniqueTyVar | ||
|
||
instance Ftv (Monotype loc) where | ||
ftv (TypeVar tv) = one tv | ||
ftv (Scalar _) = mempty | ||
ftv (TypeConstructor _ ts) = foldMap ftv ts | ||
ftv (Function t1 t2) = ftv t1 <> ftv t2 | ||
|
||
instance Ftv (Type loc) where | ||
ftv (Forall tv _ t) = ftv t `difference` one tv | ||
|
||
occurs :: Ftv a => UniqueTyVar -> a -> Bool | ||
occurs tv a = tv `member` ftv a |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
module Arbitrary.Type where | ||
|
||
import Elara.AST.Name | ||
import Elara.Data.Unique (unsafeMkUnique) | ||
import Elara.TypeInfer.Type | ||
import Elara.TypeInfer.Unique | ||
import Hedgehog (Gen) | ||
import Hedgehog.Gen qualified as Gen | ||
import Hedgehog.Range qualified as Range | ||
import Region (qualifiedTest) | ||
|
||
-- | contrary to what the name suggests, this will NOT be unique :) | ||
genUniqueTypeVar :: Gen UniqueTyVar | ||
genUniqueTypeVar = unsafeMkUnique Nothing <$> Gen.integral (Range.linear 0 100) | ||
|
||
typeConstructorNames :: [TypeName] | ||
typeConstructorNames = ["List", "Maybe", "Pair", "Box", "IO"] | ||
|
||
genMonotype :: Gen (Monotype loc) | ||
genMonotype = | ||
Gen.recursive | ||
Gen.choice | ||
[ TypeVar <$> genUniqueTypeVar | ||
, Scalar <$> Gen.enumBounded | ||
] | ||
[ TypeConstructor <$> Gen.element (qualifiedTest <$> typeConstructorNames) <*> Gen.list (Range.linear 0 2) genMonotype | ||
, Function <$> genMonotype <*> genMonotype | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
module Infer.Unify where | ||
|
||
import Arbitrary.Type (genMonotype, genUniqueTypeVar) | ||
import Elara.TypeInfer.ConstraintGeneration | ||
import Elara.TypeInfer.Type | ||
import Hedgehog (Gen, Property, evalEither, forAll, property, (===)) | ||
import Hedgehog.Gen qualified as Gen | ||
import Hedgehog.Range qualified as Range | ||
import Polysemy | ||
import Polysemy.Error | ||
import Test.Syd | ||
import Test.Syd.Hedgehog () | ||
|
||
spec :: Spec | ||
spec = describe "Type unification" $ do | ||
it "unifies type variables" prop_unify_type_vars | ||
it "unifies scalars" prop_unify_scalars | ||
it "unifies functions" prop_unify_functions | ||
it "unifies self" prop_unify_self | ||
it "fails to unify mismatched types" prop_unify_failure | ||
|
||
runUnify :: | ||
Sem '[Error UnifyError] (Substitution loc, Constraint loc) -> | ||
Either UnifyError (Substitution loc, Constraint loc) | ||
runUnify = run . runError | ||
|
||
prop_unify_type_vars :: Property | ||
prop_unify_type_vars = property $ do | ||
a <- forAll $ genUniqueTypeVar | ||
let typeVar = TypeVar a | ||
(sub, _) <- evalEither $ runUnify $ unify typeVar typeVar | ||
sub === Substitution [] | ||
|
||
prop_unify_scalars :: Property | ||
prop_unify_scalars = property $ do | ||
a <- forAll $ Gen.enumBounded | ||
let scalarType = Scalar a | ||
(sub, _) <- evalEither $ runUnify $ unify scalarType scalarType | ||
sub === Substitution [] | ||
|
||
prop_unify_self :: Property | ||
prop_unify_self = property $ do | ||
a <- forAll genMonotype | ||
(sub, _) <- evalEither $ runUnify $ unify a a | ||
sub === Substitution [] | ||
|
||
prop_unify_functions :: Property | ||
prop_unify_functions = property $ do | ||
a <- forAll genMonotype | ||
b <- forAll genMonotype | ||
(sub, _) <- evalEither $ runUnify $ unify (Function a b) (Function a b) | ||
sub === Substitution [] | ||
|
||
-- Hedgehog property: Check unification failure for mismatched types | ||
prop_unify_failure :: Property | ||
prop_unify_failure = property $ do | ||
a <- forAll genMonotype | ||
b <- forAll genMonotype | ||
-- let's come back to this later | ||
-- let result = runUnify $ unify a b | ||
-- result === Left (UnificationFailed $ "Unification failed: " <> show a <> " and " <> show b) | ||
guard $ a /= b |