1- {-# LANGUAGE DeriveFunctor, FlexibleContexts, FlexibleInstances, LambdaCase, OverloadedStrings, RecordWildCards, ScopedTypeVariables, TypeApplications #-}
1+ {-# LANGUAGE DeriveGeneric, DeriveTraversable, FlexibleContexts, FlexibleInstances, LambdaCase, OverloadedStrings, QuantifiedConstraints, RecordWildCards, ScopedTypeVariables, StandaloneDeriving, TypeApplications, TypeOperators #-}
22module Analysis.Typecheck
33( Monotype (.. )
44, Meta
5- , Polytype (PForAll , PBool , PFree , PArr )
6- , Scope
7- , Analysis.Typecheck. bind
8- , Analysis.Typecheck. instantiate
5+ , Polytype (.. )
96, typecheckingFlowInsensitive
107, typecheckingAnalysis
118) where
129
1310import Analysis.Eval
1411import Analysis.FlowInsensitive
1512import Control.Applicative (Alternative (.. ))
16- import Control.Effect
13+ import Control.Effect.Carrier
1714import Control.Effect.Fail
1815import Control.Effect.Fresh as Fresh
1916import Control.Effect.Reader hiding (Local )
2017import Control.Effect.State
2118import Control.Monad (unless )
19+ import Control.Monad.Module
2220import qualified Data.Core as Core
2321import Data.File
24- import Data.Foldable (foldl' , for_ )
22+ import Data.Foldable (for_ )
2523import Data.Function (fix )
2624import Data.Functor (($>) )
2725import qualified Data.IntMap as IntMap
2826import qualified Data.IntSet as IntSet
2927import Data.List.NonEmpty (nonEmpty )
3028import Data.Loc
3129import qualified Data.Map as Map
30+ import Data.Maybe (fromJust , fromMaybe )
3231import Data.Name as Name
32+ import Data.Scope
3333import qualified Data.Set as Set
3434import Data.Stack
3535import Data.Term
36+ import Data.Void
37+ import GHC.Generics (Generic1 )
3638import Prelude hiding (fail )
3739
38- data Monotype a
39- = MBool
40- | MUnit
41- | MString
42- | MMeta a
43- | MFree Gensym
44- | MArr (Monotype a ) (Monotype a )
45- | MRecord (Map. Map User (Monotype a ))
46- deriving (Eq , Functor , Ord , Show )
40+ data Monotype f a
41+ = Bool
42+ | Unit
43+ | String
44+ | Arr (f a ) (f a )
45+ | Record (Map. Map User (f a ))
46+ deriving (Foldable , Functor , Generic1 , Traversable )
47+
48+ deriving instance (Eq a , forall a . Eq a => Eq (f a ), Monad f ) => Eq (Monotype f a )
49+ deriving instance (Ord a , forall a . Eq a => Eq (f a )
50+ , forall a . Ord a => Ord (f a ), Monad f ) => Ord (Monotype f a )
51+ deriving instance (Show a , forall a . Show a => Show (f a )) => Show (Monotype f a )
52+
53+ instance HFunctor Monotype
54+ instance RightModule Monotype where
55+ Unit >>=* _ = Unit
56+ Bool >>=* _ = Bool
57+ String >>=* _ = String
58+ Arr a b >>=* f = Arr (a >>= f) (b >>= f)
59+ Record m >>=* f = Record ((>>= f) <$> m)
4760
4861type Meta = Int
4962
50- data Polytype
51- = PForAll Scope
52- | PUnit
53- | PBool
54- | PString
55- | PBound Int
56- | PFree Gensym
57- | PArr Polytype Polytype
58- | PRecord (Map. Map User Polytype )
59- deriving (Eq , Ord , Show )
60-
61- newtype Scope = Scope Polytype
62- deriving (Eq , Ord , Show )
63+ newtype Polytype f a = PForAll (Scope () f a )
64+ deriving (Foldable , Functor , Generic1 , Traversable )
6365
64- forAll :: Gensym -> Polytype -> Polytype
65- forAll n body = PForAll (Analysis.Typecheck. bind n body)
66+ deriving instance (Eq a , forall a . Eq a => Eq (f a ), Monad f ) => Eq (Polytype f a )
67+ deriving instance (Ord a , forall a . Eq a => Eq (f a )
68+ , forall a . Ord a => Ord (f a ), Monad f ) => Ord (Polytype f a )
69+ deriving instance (Show a , forall a . Show a => Show (f a )) => Show (Polytype f a )
6670
67- forAlls :: Foldable t => t Gensym -> Polytype -> Polytype
68- forAlls ns body = foldr forAll body ns
71+ instance HFunctor Polytype
72+ instance RightModule Polytype where
73+ PForAll b >>=* f = PForAll (b >>=* f)
6974
70- generalize :: (Carrier sig m , Member Naming sig ) => Monotype Meta -> m Polytype
71- generalize ty = namespace " generalize" $ do
72- Gensym root _ <- Name. fresh
73- pure (forAlls (map (Gensym root) (IntSet. toList (mvs ty))) (fold root ty))
74- where fold root = \ case
75- MUnit -> PUnit
76- MBool -> PBool
77- MString -> PString
78- MMeta i -> PFree (Gensym root i)
79- MFree n -> PFree n
80- MArr a b -> PArr (fold root a) (fold root b)
81- MRecord fs -> PRecord (fold root <$> fs)
8275
83- -- | Bind occurrences of a 'Gensym' in a 'Polytype' term, producing a 'Scope' in which the 'Gensym' is bound.
84- bind :: Gensym -> Polytype -> Scope
85- bind name = Scope . substIn (\ i n -> if name == n then PBound i else PFree n) (const PBound )
76+ forAll :: (Eq a , Carrier sig m , Member Polytype sig ) => a -> m a -> m a
77+ forAll n body = send (PForAll (Data.Scope. bind1 n body))
8678
87- -- | Substitute a 'Polytype' term for the free variable in a given 'Scope', producing a closed 'Polytype' term.
88- instantiate :: Polytype -> Scope -> Polytype
89- instantiate image (Scope body) = substIn (const PFree ) (\ i j -> if i == j then image else PBound j) body
79+ forAlls :: (Eq a , Carrier sig m , Member Polytype sig , Foldable t ) => t a -> m a -> m a
80+ forAlls ns body = foldr forAll body ns
9081
91- substIn :: (Int -> Gensym -> Polytype )
92- -> (Int -> Int -> Polytype )
93- -> Polytype
94- -> Polytype
95- substIn free bound = go 0
96- where go i (PFree name) = free i name
97- go i (PBound j) = bound i j
98- go i (PForAll (Scope body)) = PForAll (Scope (go (succ i) body))
99- go _ PUnit = PUnit
100- go _ PBool = PBool
101- go _ PString = PString
102- go i (PArr a b) = PArr (go i a) (go i b)
103- go i (PRecord fs) = PRecord (go i <$> fs)
82+ generalize :: Term Monotype Meta -> Term (Polytype :+: Monotype ) Void
83+ generalize ty = fromJust (closed (forAlls (IntSet. toList (mvs ty)) (hoistTerm R ty)))
10484
10585
106- typecheckingFlowInsensitive :: [File (Term Core. Core Name )] -> (Heap Name (Monotype Meta ), [File (Either (Loc , String ) Polytype )])
86+ typecheckingFlowInsensitive :: [File (Term Core. Core Name )] -> (Heap Name (Term Monotype Meta ), [File (Either (Loc , String ) ( Term ( Polytype :+: Monotype ) Void ) )])
10787typecheckingFlowInsensitive
10888 = run
10989 . runFresh
11090 . runNaming
11191 . runHeap (Gen (Gensym (Nil :> " root" ) 0 ))
112- . ( >>= traverse ( traverse ( traverse generalize)))
92+ . fmap ( fmap ( fmap ( fmap generalize)))
11393 . traverse runFile
11494
11595runFile :: ( Carrier sig m
11696 , Effect sig
11797 , Member Fresh sig
11898 , Member Naming sig
119- , Member (State (Heap Name (Monotype Meta ))) sig
99+ , Member (State (Heap Name (Term Monotype Meta ))) sig
120100 )
121101 => File (Term Core. Core Name )
122- -> m (File (Either (Loc , String ) (Monotype Meta )))
102+ -> m (File (Either (Loc , String ) (Term Monotype Meta )))
123103runFile file = traverse run file
124104 where run
125105 = (\ m -> do
126106 (subst, t) <- m
127- modify @ (Heap Name (Monotype Meta )) (substAll subst)
107+ modify @ (Heap Name (Term Monotype Meta )) (fmap ( Set. map ( substAll subst)) )
128108 pure (substAll subst <$> t))
129109 . runState (mempty :: Substitution )
130110 . runReader (fileLoc file)
@@ -139,7 +119,7 @@ runFile file = traverse run file
139119 v <$ for_ bs (unify v))
140120 . convergeTerm (fix (cacheTerm . eval typecheckingAnalysis))
141121
142- typecheckingAnalysis :: (Alternative m , Carrier sig m , Member Fresh sig , Member (State (Set. Set Constraint )) sig , Member (State (Heap Name (Monotype Meta ))) sig , MonadFail m ) => Analysis Name (Monotype Meta ) m
122+ typecheckingAnalysis :: (Alternative m , Carrier sig m , Member Fresh sig , Member (State (Set. Set Constraint )) sig , Member (State (Heap Name (Term Monotype Meta ))) sig , MonadFail m ) => Analysis Name (Term Monotype Meta ) m
143123typecheckingAnalysis = Analysis {.. }
144124 where alloc = pure
145125 bind _ _ = pure ()
@@ -152,108 +132,65 @@ typecheckingAnalysis = Analysis{..}
152132 arg <- meta
153133 assign addr arg
154134 ty <- eval body
155- pure (MArr arg ty)
135+ pure (Term ( Arr arg ty) )
156136 apply _ f a = do
157137 _A <- meta
158138 _B <- meta
159- unify (MArr _A _B) f
139+ unify (Term ( Arr _A _B) ) f
160140 unify _A a
161141 pure _B
162- unit = pure MUnit
163- bool _ = pure MBool
164- asBool b = unify MBool b >> pure True <|> pure False
165- string _ = pure MString
166- asString s = unify MString s $> mempty
142+ unit = pure ( Term Unit )
143+ bool _ = pure ( Term Bool )
144+ asBool b = unify ( Term Bool ) b >> pure True <|> pure False
145+ string _ = pure ( Term String )
146+ asString s = unify ( Term String ) s $> mempty
167147 frame = fail " unimplemented"
168148 edge _ _ = pure ()
169149 _ ... m = m
170150
171151
172- data Constraint = Monotype Meta :===: Monotype Meta
152+ data Constraint = Term Monotype Meta :===: Term Monotype Meta
173153 deriving (Eq , Ord , Show )
174154
175155infix 4 :===:
176156
177157data Solution
178- = Int := Monotype Meta
158+ = Int := Term Monotype Meta
179159 deriving (Eq , Ord , Show )
180160
181161infix 5 :=
182162
183- meta :: (Carrier sig m , Member Fresh sig ) => m (Monotype Meta )
184- meta = MMeta <$> Fresh. fresh
163+ meta :: (Carrier sig m , Member Fresh sig ) => m (Term Monotype Meta )
164+ meta = pure <$> Fresh. fresh
185165
186- unify :: (Carrier sig m , Member (State (Set. Set Constraint )) sig ) => Monotype Meta -> Monotype Meta -> m ()
166+ unify :: (Carrier sig m , Member (State (Set. Set Constraint )) sig ) => Term Monotype Meta -> Term Monotype Meta -> m ()
187167unify t1 t2
188168 | t1 == t2 = pure ()
189169 | otherwise = modify (<> Set. singleton (t1 :===: t2))
190170
191- type Substitution = IntMap. IntMap (Monotype Meta )
171+ type Substitution = IntMap. IntMap (Term Monotype Meta )
192172
193173solve :: (Carrier sig m , Member (State Substitution ) sig , MonadFail m ) => Set. Set Constraint -> m ()
194174solve cs = for_ cs solve
195175 where solve = \ case
196176 -- FIXME: how do we enforce proper subtyping? row polymorphism or something?
197- MRecord f1 :===: MRecord f2 -> traverse solve (Map. intersectionWith (:===:) f1 f2) $> ()
198- MArr a1 b1 :===: MArr a2 b2 -> solve (a1 :===: a2) *> solve (b1 :===: b2)
199- MMeta m1 :===: MMeta m2 | m1 == m2 -> pure ()
200- MMeta m1 :===: t2 -> do
177+ Term ( Record f1) :===: Term ( Record f2) -> traverse solve (Map. intersectionWith (:===:) f1 f2) $> ()
178+ Term ( Arr a1 b1) :===: Term ( Arr a2 b2) -> solve (a1 :===: a2) *> solve (b1 :===: b2)
179+ Var m1 :===: Var m2 | m1 == m2 -> pure ()
180+ Var m1 :===: t2 -> do
201181 sol <- solution m1
202182 case sol of
203183 Just (_ := t1) -> solve (t1 :===: t2)
204184 Nothing | m1 `IntSet.member` mvs t2 -> fail (" Occurs check failure: " <> show m1 <> " :===: " <> show t2)
205- | otherwise -> modify (IntMap. insert m1 t2 . subst (m1 := t2 ))
206- t1 :===: MMeta m2 -> solve (MMeta m2 :===: t1)
185+ | otherwise -> modify (IntMap. insert m1 t2 . fmap (substAll ( IntMap. singleton m1 t2) ))
186+ t1 :===: Var m2 -> solve (Var m2 :===: t1)
207187 t1 :===: t2 -> unless (t1 == t2) $ fail (" Type mismatch:\n expected: " <> show t1 <> " \n actual: " <> show t2)
208188
209189 solution m = fmap (m := ) <$> gets (IntMap. lookup m)
210190
211- substAll :: Substitutable t => Substitution -> t -> t
212- substAll s a = foldl' (flip subst) a (map (uncurry (:=) ) (IntMap. toList s))
213-
214-
215- class FreeVariables t where
216- mvs :: t -> IntSet. IntSet
217-
218- instance FreeVariables (Monotype Meta ) where
219- mvs MUnit = mempty
220- mvs MBool = mempty
221- mvs MString = mempty
222- mvs (MArr a b) = mvs a <> mvs b
223- mvs (MMeta m) = IntSet. singleton m
224- mvs (MFree _) = mempty
225- mvs (MRecord fs) = foldMap mvs fs
226-
227- instance FreeVariables Constraint where
228- mvs (t1 :===: t2) = mvs t1 <> mvs t2
229-
230- class Substitutable t where
231- subst :: Solution -> t -> t
232-
233- instance Substitutable (Monotype Meta ) where
234- subst s con = case con of
235- MUnit -> MUnit
236- MBool -> MBool
237- MString -> MString
238- MArr a b -> MArr (subst s a) (subst s b)
239- MMeta m'
240- | m := t <- s
241- , m == m' -> t
242- | otherwise -> MMeta m'
243- MFree n -> MFree n
244- MRecord fs -> MRecord (subst s <$> fs)
245-
246- instance Substitutable Constraint where
247- subst s (t1 :===: t2) = subst s t1 :===: subst s t2
248-
249- instance Substitutable Solution where
250- subst s (m := t) = m := subst s t
251-
252- instance Substitutable a => Substitutable (IntMap. IntMap a ) where
253- subst s = IntMap. map (subst s)
254191
255- instance ( Ord a , Substitutable a ) => Substitutable ( Set. Set a ) where
256- subst s = Set. map (subst s)
192+ mvs :: Foldable t => t Meta -> IntSet. IntSet
193+ mvs = foldMap IntSet. singleton
257194
258- instance Substitutable v => Substitutable ( Map. Map k v ) where
259- subst s = fmap (subst s)
195+ substAll :: Monad t => IntMap. IntMap ( t Meta ) -> t Meta -> t Meta
196+ substAll s a = a >>= \ i -> fromMaybe ( pure i) ( IntMap. lookup i s)
0 commit comments