on master help sign in
Started using traversals instead of custom folds
commit1086c0801c286a890183534646c606d13c88e680 authoriko <ilyakooo0@gmail.com> dateSat 3 Apr 2021, 15:59 (6 years ago) parenta81aa0a
3 files changed+83−115
package.yaml+3 src/Tix/Typechecker.hs+15−41 src/Tix/Types.hs+65−74
package.yaml+3
@@ -38,6 +38,7 @@ dependencies:
3838 - prettyprinter
3939 - range-set-list
4040 - generic-data
41+ - generic-lens
4142
4243library:
4344 source-dirs: src
@@ -93,3 +94,5 @@ default-extensions:
9394 - DeriveGeneric
9495 - DerivingVia
9596 - RecordWildCards
97+ - FunctionalDependencies
98+ - DeriveDataTypeable
src/Tix/Typechecker.hs+15−41
@@ -10,6 +10,7 @@ module Tix.Typechecker
1010where
1111
1212import Control.Exception (assert)
13+import Control.Lens hiding (Empty, List, cons, equality, set, set')
1314import Control.Monad
1415import Control.Monad.Freer
1516import Control.Monad.Freer.Fresh
@@ -22,7 +23,6 @@ import Data.Act
2223import qualified Data.Aeson as A
2324import Data.Fix
2425import Data.Foldable
25−import Data.Functor
2626import Data.Functor.Contravariant
2727import Data.Group hiding ((~~))
2828import Data.List.NonEmpty (NonEmpty (..))
@@ -110,26 +110,12 @@ close (Predicate f) =
110110 where
111111 -- State is the sequential number, Reader is the binding context number
112112 close' :: Scheme -> Eff '[State Int, Reader Int, State TDeBruijnMap] Scheme
113− close' (preds :=> t) =
114− (:=>) <$> (Preds <$> closePred `traverse` unPreds preds) <*> closeType t
115−
116− closeType :: NType -> Eff '[State Int, Reader Int, State TDeBruijnMap] NType
117− closeType = \case
118− x@(NBruijn _) -> return x
119− x@(NAtomic _) -> return x
120− (NTypeVariable tv) | f tv -> NBruijn <$> newbruijn tv
121− x@(NTypeVariable _) -> return x
122− (x :-> y) -> bndCtx $ (:->) <$> close' x <*> close' y
123− (List x) -> bndCtx $ List <$> close' x
124− (NAttrSet x) -> bndCtx $ NAttrSet <$> traverse close' x
125−
126− closePred :: Pred -> Eff '[State Int, Reader Int, State TDeBruijnMap] Pred
127− closePred = \case
128− (Update x y z) -> bndCtx $ Update <$> closeType x <*> closeType y <*> closeType z
129− (HasField t (k, v)) -> bndCtx $ do
130− t' <- closeType t
131− v' <- close' v
132− return $ HasField t' (k, v')
113+ close' =
114+ traverseNTypesWith bndCtx %%~ \case
115+ x@(TBruijn _) -> return x
116+ x@(TAtomic _) -> return x
117+ (TTypeVariable tv) | f tv -> TBruijn <$> newbruijn tv
118+ x@(TTypeVariable _) -> return x
133119
134120 bndCtx m = do
135121 modify @TDeBruijnMap (SM.shift 1)
@@ -381,21 +367,11 @@ instantiate ::
381367instantiate = evalState M.empty . instantiateScheme
382368 where
383369 instantiateScheme :: forall. Scheme -> Eff (State (Map DeBruijn TypeVariable) ': effs) Scheme
384− instantiateScheme (ps :=> t) =
385− (:=>) <$> (Preds <$> traverse instantiatePred (unPreds ps)) <*> instantiate' t
386−
387− instantiatePred :: forall. Pred -> Eff (State (Map DeBruijn TypeVariable) ': effs) Pred
388− instantiatePred = \case
389− (Update x y z) -> Update <$> instantiate' x <*> instantiate' y <*> instantiate' z
390− (x `HasField` (f, y)) -> HasField <$> instantiate' x <*> ((f,) <$> instantiate y)
391−
392− instantiate' :: forall. NType -> Eff (State (Map DeBruijn TypeVariable) ': effs) NType
393− instantiate' x@(NTypeVariable _) = return x
394− instantiate' (NBruijn db) = NTypeVariable <$> freshInst db
395− instantiate' (x :-> y) = (:->) <$> instantiateScheme x <*> instantiateScheme y
396− instantiate' (List x) = List <$> instantiateScheme x
397− instantiate' (NAttrSet xs) = NAttrSet <$> traverse instantiateScheme xs
398− instantiate' x@(NAtomic _) = return x
370+ instantiateScheme =
371+ traverseNTypes %%~ \case
372+ (TBruijn db) -> TTypeVariable <$> freshInst db
373+ x@(TAtomic _) -> return x
374+ x@(TTypeVariable _) -> return x
399375
400376 freshInst :: DeBruijn -> Eff (State (Map DeBruijn TypeVariable) ': effs) TypeVariable
401377 freshInst db = do
@@ -611,11 +587,9 @@ inferGeneral :: NExprLoc -> InferM Scheme
611587inferGeneral x = traceSubtree (showExpr x) $ do
612588 (((t, subs), cs), range) <-
613589 traceSubtree "subexpressions" . registerTypeVariables . runConstraintEnv $ do
614− infer x >>= \case
615− (cs :=> t) -> do
616− cs' <- solveConstraints cs
617− return $ cs' :=> t
618− u -> return u
590+ infer x >>= \(cs :=> t) -> do
591+ cs' <- solveConstraints cs
592+ return $ cs' :=> t
619593 traceSubtree "received" $ do
620594 traceValue "type" $ renderPretty t
621595 traceValue "substitutions" $ prettySubstitution subs
src/Tix/Types.hs+65−74
@@ -10,15 +10,18 @@ module Tix.Types
1010 (=>>),
1111 (//),
1212 Preds (..),
13− foldNTypeM,
14− foldNType,
15− NTypeFolder (..),
13+ traverseNTypesWith,
14+ traverseNTypes,
15+ TerminalNType (..),
1616 )
1717where
1818
19−import Control.Applicative
19+import Control.Lens hiding (List)
20+import Data.Bifunctor
21+import Data.Data (Data)
22+import Data.Data.Lens
2023import Data.Foldable
21−import Data.Functor.Identity
24+import Data.Generics.Sum.Subtype
2225import qualified Data.List as L
2326import Data.Map (Map)
2427import qualified Data.Map as M
@@ -30,6 +33,7 @@ import qualified Data.Text.Lazy.Builder as T
3033import GHC.Exts
3134import Generic.Data
3235import Prettyprinter
36+import Type.Reflection
3337
3438data Pred
3539 = -- | '(x // y) ~ z'
@@ -41,17 +45,18 @@ data Pred
4145 !NType
4246 -- ^ z
4347 | !NType `HasField` !(Text, Scheme)
44− deriving stock (Eq, Ord, Show)
48+ deriving stock (Eq, Ord, Show, Data, Generic)
4549
4650-- this seems bad. It should not drop constraints.
4751(//) :: Scheme -> Scheme -> Scheme -> Pred
4852(//) (_ :=> x) (_ :=> y) (_ :=> z) = Update x y z
4953
5054data Scheme = Preds :=> !NType
51− deriving stock (Eq, Ord, Show)
55+ deriving stock (Eq, Ord, Show, Data, Generic)
5256
5357newtype Preds = Preds {unPreds :: [Pred]}
5458 deriving newtype (Show, Eq, Ord, Semigroup, Monoid, IsList)
59+ deriving stock (Data, Generic)
5560
5661(=>>) :: Preds -> Scheme -> Scheme
5762[] =>> x = x
@@ -60,52 +65,34 @@ xs =>> (ys :=> u) = (xs <> ys) :=> u
6065scheme :: NType -> Scheme
6166scheme t = [] :=> t
6267
63−data NTypeFolder a = NTypeFolder
64− { variableFolder :: TypeVariable -> a,
65− deBruijnFolder :: DeBruijn -> a,
66− atomicFolder :: AtomicType -> a,
67− compositeFolder :: a -> a
68− }
69− deriving stock (Generic)
70− deriving (Semigroup, Monoid) via Generically (NTypeFolder a)
71−
72−class TypeFoldable t where
73− foldNTypeM :: (Applicative m, Monoid a) => NTypeFolder (m a) -> t -> m a
74−
75−instance TypeFoldable Scheme where
76− foldNTypeM tf (Preds ps :=> t) = foldA [foldAType tf ps, foldNTypeM tf t]
77−
78−instance TypeFoldable a => TypeFoldable [a] where
79− foldNTypeM tf = foldAType tf
80−
81−instance TypeFoldable Pred where
82− foldNTypeM tf (Update x y z) = foldAType tf [x, y, z]
83− foldNTypeM tf (HasField x (_, z)) = foldA [foldNTypeM tf x, foldNTypeM tf z]
84−
85−instance TypeFoldable NType where
86− foldNTypeM NTypeFolder {variableFolder = f} (NTypeVariable x) = f x
87− foldNTypeM NTypeFolder {deBruijnFolder = f} (NBruijn x) = f x
88− foldNTypeM NTypeFolder {atomicFolder = f} (NAtomic x) = f x
89− foldNTypeM tf@NTypeFolder {compositeFolder = f} (x :-> y) = f $ foldAType tf [x, y]
90− foldNTypeM tf@NTypeFolder {compositeFolder = f} (List x) = f $ foldNTypeM tf x
91− foldNTypeM tf@NTypeFolder {compositeFolder = f} (NAttrSet x) = f $ foldAType tf $ M.elems x
92−
93−foldNType :: (Monoid a, TypeFoldable x) => NTypeFolder a -> x -> a
94−foldNType NTypeFolder {..} = runIdentity . foldNTypeM tf
95− where
96− tf =
97− NTypeFolder
98− { variableFolder = Identity . variableFolder,
99− deBruijnFolder = Identity . deBruijnFolder,
100− atomicFolder = Identity . atomicFolder,
101− compositeFolder = Identity . compositeFolder . runIdentity
102− }
103−
104−foldAType :: (Monoid a, Applicative f, TypeFoldable t) => NTypeFolder (f a) -> [t] -> f a
105−foldAType tf ne = foldA $ fmap (foldNTypeM tf) ne
106−
107−foldA :: (Monoid a, Applicative f) => [f a] -> f a
108−foldA = foldr (liftA2 (<>)) (pure mempty)
68+data TerminalNType
69+ = TAtomic !AtomicType
70+ | TTypeVariable !TypeVariable
71+ | TBruijn !DeBruijn
72+ deriving stock (Show, Generic)
73+
74+traverseNTypesWith ::
75+ (Data s, Applicative f) => (forall x. f x -> f x) -> (TerminalNType -> f TerminalNType) -> s -> f s
76+traverseNTypesWith ctx f s = case eqTypeRep (typeOf s) (typeRep @NType) of
77+ Just HRefl | Just _ <- projectSub @TerminalNType s -> _Sub @TerminalNType f s
78+ Just HRefl -> ctx $ (template @_ @NType . traverseNTypesWith ctx) f s
79+ _ -> (template @_ @NType . traverseNTypesWith ctx) f s
80+{-# SPECIALIZE traverseNTypesWith ::
81+ Applicative f => (forall x. f x -> f x) -> (TerminalNType -> f TerminalNType) -> NType -> f NType
82+ #-}
83+{-# SPECIALIZE traverseNTypesWith ::
84+ Applicative f => (forall x. f x -> f x) -> (TerminalNType -> f TerminalNType) -> Scheme -> f Scheme
85+ #-}
86+{-# SPECIALIZE traverseNTypesWith ::
87+ Monoid r => (forall x. Const r x -> Const r x) -> (TerminalNType -> Const r TerminalNType) -> NType -> Const r NType
88+ #-}
89+{-# SPECIALIZE traverseNTypesWith ::
90+ Monoid r => (forall x. Const r x -> Const r x) -> (TerminalNType -> Const r TerminalNType) -> Scheme -> Const r Scheme
91+ #-}
92+
93+traverseNTypes :: Data s => Traversal' s TerminalNType
94+traverseNTypes = traverseNTypesWith id
95+{-# INLINE traverseNTypes #-}
10996
11097data NType
11198 = NTypeVariable !TypeVariable
@@ -114,7 +101,7 @@ data NType
114101 | !Scheme :-> !Scheme
115102 | List !Scheme
116103 | NAttrSet !(Map Text Scheme)
117− deriving stock (Eq, Ord, Show)
104+ deriving stock (Eq, Ord, Show, Data, Generic)
118105
119106data AtomicType
120107 = Integer
@@ -124,13 +111,14 @@ data AtomicType
124111 | Path
125112 | Null
126113 | URI
127− deriving stock (Eq, Ord, Show)
114+ deriving stock (Eq, Ord, Show, Data, Generic)
128115
129116data DeBruijn = DeBruijn !Int !Int
130− deriving stock (Show, Eq, Ord)
117+ deriving stock (Show, Eq, Ord, Data)
131118
132119newtype TypeVariable = TypeVariable Int
133120 deriving newtype (Eq, Ord, Enum, Bounded)
121+ deriving stock (Data)
134122
135123instance Show TypeVariable where
136124 show (TypeVariable n) = "〚" <> show n <> "〛"
@@ -177,15 +165,16 @@ showNType t = TL.toStrict . T.toLazyText $ showNType' 0 t
177165-- (current) binding context.
178166-- So variables that are bound in one of the inner contexts will have a negative
179167-- binding context number.
180−getAllDeBurjins :: TypeFoldable x => x -> Set DeBruijn
168+getAllDeBurjins :: Data x => x -> Set DeBruijn
181169getAllDeBurjins =
182− foldNType
183− NTypeFolder
184− { variableFolder = const S.empty,
185− deBruijnFolder = S.singleton,
186− atomicFolder = const S.empty,
187− compositeFolder = S.mapMonotonic (\(DeBruijn i j) -> DeBruijn (i - 1) j)
188− }
170+ view $
171+ traverseNTypesWith (first $ S.mapMonotonic (\(DeBruijn i j) -> DeBruijn (i - 1) j))
172+ . to
173+ ( \case
174+ TAtomic _ -> S.empty
175+ TBruijn b -> S.singleton b
176+ TTypeVariable _ -> S.empty
177+ )
189178
190179-- | Get all De Bruijn type variables that were bound in the the outermost
191180-- (current) binding context.
@@ -195,17 +184,19 @@ getDeBurjins t = getDeBurjins' t 0
195184
196185-- | Gets all De Bruijn variables with the given binding context offset.
197186-- Only returns the second indexes.
198−getDeBurjins' :: TypeFoldable x => x -> Int -> Set Int
187+getDeBurjins' :: Data x => x -> Int -> Set Int
199188getDeBurjins' =
200− foldNType
201− NTypeFolder
202− { variableFolder = \_ _ -> S.empty,
203− deBruijnFolder = \t n -> case t of
204− DeBruijn m j | m == n -> S.singleton j
205− _ -> S.empty,
206− atomicFolder = \_ _ -> S.empty,
207− compositeFolder = \f n -> f (n + 1)
208− }
189+ view $
190+ traverseNTypesWith (\(Const f) -> Const (\n -> f (n + 1)))
191+ . to
192+ ( \case
193+ TAtomic _ -> const S.empty
194+ TBruijn (DeBruijn m j) -> \n ->
195+ if m == n
196+ then S.singleton j
197+ else S.empty
198+ TTypeVariable _ -> const S.empty
199+ )
209200
210201showAtomicType :: AtomicType -> T.Builder
211202showAtomicType Integer = "Integer"