1+ {-# LANGUAGE DeriveAnyClass #-}
12{-# LANGUAGE AllowAmbiguousTypes #-}
23{-# LANGUAGE BangPatterns #-}
34{-# LANGUAGE BlockArguments #-}
4243
4344module Main (main , specMain ) where
4445
46+
4547#if __GLASGOW_HASKELL__ >= 906
48+ import Data.Tuple
49+ import Data.Fix
50+ import qualified Control.Unification.Types as FD
51+ import Control.Monad.Trans.Except
4652import qualified Control.Unification as FD
53+ import qualified Control.Unification.STVar as FD
4754import GHC.Generics (Generic1 )
4855import Control.Monad
4956#endif
@@ -52,6 +59,7 @@ import Control.Monad
5259-- e.g. 'Data.Graph' becomes 'Graph', and are then exposed to the Hell
5360-- guest language as such.
5461
62+ import Control.Monad.ST
5563import qualified Data.CaseInsensitive as CI
5664import Data.CaseInsensitive (CI , FoldCase )
5765import qualified Network.HTTP.Types as Http
@@ -211,7 +219,7 @@ compileFile stats filePath = do
211219 case lookup " main" dterms of
212220 Nothing -> error " No main declaration!"
213221 Just main' -> do
214- inferred <- inferExp (nestStat stats) main'
222+ inferred <- infer_exp (nestStat stats) main'
215223 case inferred of
216224 Left err -> error $ prettyString err
217225 Right uterm -> do
@@ -1636,7 +1644,10 @@ data InferError
16361644 = UnifyError UnifyError
16371645 | ZonkError ZonkError
16381646 | ElabError ElaborateError
1639- deriving (Show )
1647+ | ST_mapping_error
1648+ | ST_unify_error
1649+ | ST_apply_bindings_error
1650+ deriving instance Show InferError
16401651
16411652-- | Note: All types in the input are free of metavars. There is an
16421653-- intermediate phase in which there are metavars, but then they're
@@ -1665,6 +1676,19 @@ inferExp stats uterm = do
16651676 emitStat stats " zonk" (t3 - t2)
16661677 pure $ Right sterm
16671678
1679+ infer_exp ::
1680+ StatsEnabled ->
1681+ UTerm () ->
1682+ IO (Either InferError (UTerm SomeTypeRep ))
1683+ infer_exp stats uterm = do
1684+ t0 <- getTime
1685+ case elaborate uterm of
1686+ Left elabError -> pure $ Left $ ElabError elabError
1687+ Right (iterm, equalities) -> do
1688+ t1 <- getTime
1689+ emitStat stats " elaborate" (t1 - t0)
1690+ st_unify stats equalities iterm
1691+
16681692-- | Zonk a type and then convert it to a type: t :: *
16691693zonkToStarType :: Map IMetaVar (IRep IMetaVar ) -> IRep IMetaVar -> Either ZonkError SomeTypeRep
16701694zonkToStarType subs irep = do
@@ -2646,6 +2670,103 @@ data Ty a
26462670 | TyFun a a
26472671 | TyCon SomeTypeRep
26482672 deriving (Functor , Traversable , Foldable , Eq , Ord , Show , Generic1 )
2673+ -- Below: Needed for FD.freeVar (note for myself, not audience)
2674+ deriving instance FD. Unifiable Ty
2675+
2676+ -- WIP: At this point we want, preferably, a function that goes
2677+ -- from an (IRep IMetaVar) to SomeTypeRep in one go, which inferExp can
2678+ -- use to traverse f iterm to get UTerm SomeTypeRep. Or it receives the expr
2679+ -- to traverse over, due to the ST monadness.
2680+ --
2681+ -- Some key ingredients:
2682+ --
2683+ -- to_sometyperep :: Fix Ty -> Either ZonkError SomeTypeRep
2684+ -- irep_to_uterm :: IRep v -> FD.UTerm Ty v
2685+ -- FD.applyBindings :: UTerm t v -> em m (UTerm t v)
2686+ --
2687+ -- I'd say we want to:
2688+ --
2689+ -- 1) Convert the IRep IMetaVar to UTerm t v using the (Map IMetaVar (STVar ..)) map.
2690+ -- 2) Apply bindings to fully flesh out the type.
2691+ -- 3) Zonk it, going directly from FD.UTerm Ty straight to SomeTypeRep
2692+ -- (tweak to_sometyperep to work with UTerm Ty rather than Fix Ty)
2693+ --
2694+ -- That should be all that's needed?
2695+
2696+ -- Unify all the constraints in @equalities@, zonk and update the term and return it.
2697+ st_unify :: Traversable t
2698+ => StatsEnabled
2699+ -> Set (Equality (IRep IMetaVar ))
2700+ -> t (IRep IMetaVar )
2701+ -> IO (Either InferError (t SomeTypeRep ))
2702+ st_unify stats set term = do
2703+ t1 <- getTime
2704+ let result =
2705+ FD. runSTBinding do
2706+ -- Thaw the equalities.
2707+ (equalities, mapping) <- run_stize $ stize_equalities $ Set. toList set
2708+ -- Unify the mutable equalities into the ambient environment.
2709+ result <- runExceptT $ st_unifier_ equalities
2710+ case result of
2711+ Left err -> pure $ Left ST_unify_error
2712+ Right () -> do
2713+ -- Apply bindings, zonk and freeze all the types across the term.
2714+ runExceptT $
2715+ for term \ irepmv -> do
2716+ uterm <- for (irep_to_uterm irepmv) \ imv ->
2717+ case Map. lookup imv mapping of
2718+ Nothing -> throwE $ ST_mapping_error
2719+ Just stvar -> pure stvar
2720+ uterm' <- withExceptT (const ST_apply_bindings_error ) $ st_apply uterm
2721+ except $ first ZonkError $
2722+ to_sometyperep
2723+ mapping
2724+ uterm'
2725+ case result of
2726+ Left err -> pure $ Left err
2727+ Right (! term') -> do
2728+ t2 <- getTime
2729+ emitStat stats " unify-and-zonk" (t2 - t1)
2730+ pure $ Right term'
2731+
2732+ -- Apply bindings; this type signature avoids type inference problems.
2733+ st_apply :: FD. UTerm Ty (FD. STVar s Ty )
2734+ -> ExceptT (FD. UFailure Ty (FD. STVar s Ty )) (FD. STBinding s ) (FD. UTerm Ty (FD. STVar s Ty ))
2735+ st_apply = FD. applyBindings
2736+
2737+ -- Unify all the equality constraints provided.
2738+ st_unifier_ :: [Equality (FD. UTerm Ty (FD. STVar s Ty ))]
2739+ -> ExceptT (FD. UFailure Ty (FD. STVar s Ty )) (FD. STBinding s ) ()
2740+ st_unifier_ = traverse_ \ (Equality src a b) -> void $ FD. unify a b
2741+
2742+ -- Run an ST-izing operation, and return the mapping from the original IMetaVars to the STVars, so that they can be recovered later.
2743+ run_stize :: StateT (Map IMetaVar (FD. STVar s Ty )) (FD. STBinding s ) x -> FD. STBinding s (x , Map IMetaVar (FD. STVar s Ty ))
2744+ run_stize = flip runStateT (mempty :: Map IMetaVar (FD. STVar s Ty ))
2745+
2746+ -- ST-ize the metavars in all types in the equality constraints set
2747+ stize_equalities :: [Equality (IRep IMetaVar )] -> StateT (Map IMetaVar (FD. STVar s Ty )) (FD. STBinding s ) [Equality (FD. UTerm Ty (FD. STVar s Ty ))]
2748+ stize_equalities = traverse stize_equality
2749+
2750+ -- ST-ize the metavars in all types in the equality's types on both sides, it also
2751+ -- is exactly where conversion from IRep to UTerm Ty occurs.
2752+ stize_equality :: Equality (IRep IMetaVar ) -> StateT (Map IMetaVar (FD. STVar s Ty )) (FD. STBinding s ) (Equality (FD. UTerm Ty (FD. STVar s Ty )))
2753+ stize_equality (Equality loc a b) = do
2754+ Equality loc <$> stize_uterm (irep_to_uterm a) <*> stize_uterm (irep_to_uterm b)
2755+
2756+ -- ST-ize the metavars in a uterm
2757+ stize_uterm :: FD. UTerm Ty IMetaVar -> StateT (Map IMetaVar (FD. STVar s Ty )) (FD. STBinding s ) (FD. UTerm Ty (FD. STVar s Ty ))
2758+ stize_uterm = traverse stize_imetavar
2759+
2760+ -- ST-ize this metavar and remember that it was done
2761+ stize_imetavar :: IMetaVar -> StateT (Map IMetaVar (FD. STVar s Ty )) (FD. STBinding s ) (FD. STVar s Ty )
2762+ stize_imetavar = \ v -> do
2763+ mexisting <- gets (Map. lookup v)
2764+ case mexisting of
2765+ Just stv -> pure stv
2766+ Nothing -> do
2767+ stv <- lift FD. freeVar
2768+ modify' (Map. insert v stv)
2769+ pure stv
26492770
26502771-- <bijection>
26512772irep_to_uterm :: IRep v -> FD. UTerm Ty v
@@ -2654,14 +2775,36 @@ irep_to_uterm = \case
26542775 IApp f x -> FD. UTerm (TyApp (irep_to_uterm f) (irep_to_uterm x))
26552776 IFun f x -> FD. UTerm (TyFun (irep_to_uterm f) (irep_to_uterm x))
26562777 ICon t -> FD. UTerm $ TyCon t
2657- uterm_to_irep :: FD. UTerm Ty v -> IRep v
2658- uterm_to_irep = \ case
2659- FD. UVar v -> IVar v
2660- FD. UTerm (TyApp f x) -> IApp (uterm_to_irep f) (uterm_to_irep x)
2661- FD. UTerm (TyFun f x) -> IFun (uterm_to_irep f) (uterm_to_irep x)
2662- FD. UTerm (TyCon t) -> ICon t
26632778-- </bijection>
26642779
2780+ -- | (unification-fd edition)
2781+ -- A complete implementation of conversion from the inferer's type
2782+ -- rep to some star type, ready for the type checker.
2783+ -- Jumps straight from UTerm Ty to SomeTypeRep in one go; handles
2784+ -- ambiguous vars and kind errors here.
2785+ to_sometyperep :: forall v . Eq v => (Map IMetaVar v ) ->
2786+ FD. UTerm Ty v -> Either ZonkError SomeTypeRep
2787+ to_sometyperep mapping t = do
2788+ go t
2789+ where
2790+ go :: FD. UTerm Ty v -> Either ZonkError SomeTypeRep
2791+ go = \ case
2792+ FD. UVar k -> Left $ ST_ambiguous_var (List. lookup k $ map swap $ Map. toList mapping)
2793+ FD. UTerm (TyCon someTypeRep) -> pure someTypeRep
2794+ FD. UTerm (TyFun a b) -> do
2795+ a' <- go a
2796+ b' <- go b
2797+ case (a', b') of
2798+ (StarTypeRep aRep, StarTypeRep bRep) ->
2799+ pure $ StarTypeRep (Type. Fun aRep bRep)
2800+ _ -> Left ZonkKindError
2801+ FD. UTerm (TyApp f a) -> do
2802+ f' <- go f
2803+ a' <- go a
2804+ case applyTypes f' a' of
2805+ Just someTypeRep -> pure someTypeRep
2806+ _ -> Left ZonkKindError
2807+
26652808--------------------------------------------------------------------------------
26662809-- Inference type representation
26672810
@@ -2675,6 +2818,7 @@ data IRep v
26752818data ZonkError
26762819 = ZonkKindError
26772820 | AmbiguousMetavar IMetaVar
2821+ | ST_ambiguous_var (Maybe IMetaVar )
26782822 deriving (Show )
26792823
26802824-- | A complete implementation of conversion from the inferer's type
@@ -3109,6 +3253,11 @@ instance (Pretty a) => Pretty (IRep a) where
31093253instance Pretty ZonkError where
31103254 pretty = \ case
31113255 ZonkKindError -> " Kind error."
3256+ ST_ambiguous_var imetavar -> " (ST) Ambiguous meta variable: "
3257+ <> maybe " ???" pretty imetavar
3258+ <> " \n "
3259+ <> " arising from "
3260+ <> maybe " ???" (pretty . (. srcSpanInfo)) imetavar
31123261 AmbiguousMetavar imetavar ->
31133262 " Ambiguous meta variable: "
31143263 <> pretty imetavar
0 commit comments