diff options
Diffstat (limited to 'Type.hs')
-rw-r--r-- | Type.hs | 1707 |
1 files changed, 0 insertions, 1707 deletions
diff --git a/Type.hs b/Type.hs deleted file mode 100644 index af0a1206..00000000 --- a/Type.hs +++ /dev/null | |||
@@ -1,1707 +0,0 @@ | |||
1 | {-# LANGUAGE OverloadedStrings #-} | ||
2 | {-# LANGUAGE LambdaCase #-} | ||
3 | {-# LANGUAGE PatternSynonyms #-} | ||
4 | {-# LANGUAGE DeriveFunctor #-} | ||
5 | {-# LANGUAGE DeriveFoldable #-} | ||
6 | {-# LANGUAGE DeriveTraversable #-} | ||
7 | {-# LANGUAGE GeneralizedNewtypeDeriving #-} | ||
8 | {-# LANGUAGE NoMonomorphismRestriction #-} | ||
9 | {-# LANGUAGE TypeSynonymInstances #-} | ||
10 | {-# LANGUAGE FlexibleInstances #-} | ||
11 | {-# LANGUAGE FlexibleContexts #-} | ||
12 | {-# LANGUAGE MultiParamTypeClasses #-} | ||
13 | {-# LANGUAGE StandaloneDeriving #-} | ||
14 | {-# LANGUAGE ViewPatterns #-} | ||
15 | {-# LANGUAGE TypeFamilies #-} | ||
16 | {-# LANGUAGE ScopedTypeVariables #-} | ||
17 | {-# LANGUAGE UndecidableInstances #-} | ||
18 | module Type where | ||
19 | |||
20 | import Data.Function | ||
21 | import Data.Char | ||
22 | import Data.Either | ||
23 | import Data.String | ||
24 | import Data.Maybe | ||
25 | import Data.List | ||
26 | import Data.Set (Set) | ||
27 | import qualified Data.Set as Set | ||
28 | import Data.Map (Map) | ||
29 | import qualified Data.Map as Map | ||
30 | import Data.Monoid | ||
31 | import Data.Foldable hiding (foldr) | ||
32 | import Data.Traversable | ||
33 | import Control.Monad.Except | ||
34 | import Control.Monad.State | ||
35 | import Control.Monad.Identity | ||
36 | import Control.Monad.Reader | ||
37 | import Control.Monad.Writer | ||
38 | import Control.Applicative | ||
39 | import Control.Arrow hiding ((<+>)) | ||
40 | import Text.Parsec.Pos | ||
41 | import Text.Parsec.Error | ||
42 | import GHC.Exts (Constraint) | ||
43 | import Debug.Trace | ||
44 | |||
45 | import ParserUtil (ParseError) | ||
46 | import Pretty | ||
47 | |||
48 | trace' x = trace (ppShow x) x | ||
49 | |||
50 | (<&>) = flip (<$>) | ||
51 | |||
52 | -------------------------------------------------------------------------------- literals | ||
53 | |||
54 | data Lit | ||
55 | = LInt Integer | ||
56 | | LNat Int -- invariant property: >= 0 | ||
57 | | LChar Char | ||
58 | | LString String | ||
59 | | LFloat Double | ||
60 | deriving (Eq, Ord) | ||
61 | |||
62 | -- literals in expressions | ||
63 | pattern EInt a = ELit (LInt a) | ||
64 | pattern ENat a = ELit (LNat a) | ||
65 | pattern EChar a = ELit (LChar a) | ||
66 | pattern EString a = ELit (LString a) | ||
67 | pattern EFloat a = ELit (LFloat a) | ||
68 | |||
69 | -------------------------------------------------------------------------------- patterns | ||
70 | |||
71 | -- TODO: remove | ||
72 | data Pat_ t c v b -- type; constructor info; variable info; sub-pattern | ||
73 | = PLit_ Lit | ||
74 | | PVar_ t v | ||
75 | | PCon_ t c [b] | ||
76 | | PTuple_ [b] | ||
77 | | PRecord_ [(Name, b)] | ||
78 | | PAt_ v b -- used before pattern compilation | ||
79 | | Wildcard_ t -- TODO: merge into PVar | ||
80 | -- aux | ||
81 | | PPrec_ b [(b{-TODO: Name-}, b)] -- used before precedence calculation | ||
82 | deriving (Functor,Foldable,Traversable) | ||
83 | |||
84 | -- TODO: remove | ||
85 | instance Eq Pat where (==) = error "Eq Pat" | ||
86 | instance Ord Pat where compare = error "Ord Pat" | ||
87 | |||
88 | mapPat :: (t -> t') -> (c -> c') -> (v -> v') -> Pat_ t c v b -> Pat_ t' c' v' b | ||
89 | mapPat tf f g = \case | ||
90 | PLit_ l -> PLit_ l | ||
91 | PVar_ t v -> PVar_ (tf t) $ g v | ||
92 | PCon_ t c p -> PCon_ (tf t) (f c) p | ||
93 | PTuple_ p -> PTuple_ p | ||
94 | PRecord_ p -> PRecord_ p -- $ map (g *** id) p | ||
95 | PAt_ v p -> PAt_ (g v) p | ||
96 | Wildcard_ t -> Wildcard_ (tf t) | ||
97 | PPrec_ b bs -> PPrec_ b bs | ||
98 | |||
99 | -------------------------------------------- | ||
100 | |||
101 | data PatR = PatR Range (Pat_ ExpR Name Name PatR) | ||
102 | |||
103 | -- TODO: remove | ||
104 | pattern PatR' a <- PatR _ a where | ||
105 | PatR' a = PatR mempty a | ||
106 | |||
107 | pattern PVar' a b = PatR a (PVar_ TWildcard b) | ||
108 | pattern PCon' a b c = PatR a (PCon_ TWildcard b c) | ||
109 | |||
110 | -------------------------------------------- | ||
111 | |||
112 | type Pat = PatR | ||
113 | |||
114 | pattern Pat a <- PatR _ a where | ||
115 | Pat a = PatR mempty a | ||
116 | |||
117 | pattern PAt v l = Pat (PAt_ v l) | ||
118 | pattern PLit l = Pat (PLit_ l) | ||
119 | pattern PVar t l = Pat (PVar_ t l) | ||
120 | pattern PCon t c l = Pat (PCon_ t c l) | ||
121 | pattern PTuple l = Pat (PTuple_ l) | ||
122 | pattern Wildcard t = Pat (Wildcard_ t) | ||
123 | |||
124 | patternVars' :: ParPat Exp -> [Name] | ||
125 | patternVars' = concatMap $ \case | ||
126 | PatVar n -> [n] | ||
127 | PatCon _ ps -> foldMap patternVars' ps | ||
128 | PatLit{} -> [] | ||
129 | ViewPat _ p -> patternVars' p | ||
130 | PatPrec p ps -> patternVars' p ++ foldMap patternVars' (map snd ps) | ||
131 | |||
132 | patternVars :: Pat -> [(Name, Exp)] | ||
133 | patternVars (Pat p) = case p of | ||
134 | PVar_ t v -> [(v, t)] | ||
135 | PAt_ v p -> [(v, tyOfPat p)] | ||
136 | p -> foldMap patternVars p | ||
137 | |||
138 | -------------------------------------------------------------------------------- expressions | ||
139 | |||
140 | data Exp_ v p b -- TODO: remove p | ||
141 | = Star_ | ||
142 | | ELit_ Lit | ||
143 | |||
144 | | EVar_ b v | ||
145 | | TCon_ b v -- TODO: use it or remove it | ||
146 | | TWildcard_ -- star kinded type variable | ||
147 | -- | TFun_ v [a] -- TODO | ||
148 | |||
149 | | Forall_ Visibility (Maybe v) b b | ||
150 | | ELam_ (Maybe b){-Just:hidden + type-} p b | ||
151 | | EApp_ b b b | ||
152 | | ETyApp_ b b b | ||
153 | | EPrec_ b [(b, b)] -- aux: used only before precedence calculation | ||
154 | | ELet_ p b b -- TODO: remove? | ||
155 | |||
156 | | TRecord_ (Map v b) | ||
157 | | ERecord_ [(Name, b)] | ||
158 | | EFieldProj_ b Name | ||
159 | |||
160 | | TTuple_ [b] -- TODO: remove? | ||
161 | | ETuple_ [b] -- TODO: remove? | ||
162 | | ENamedRecord_ Name [(Name, b)] | ||
163 | |||
164 | | WRefl_ b | ||
165 | | CEq_ b (TypeFun v b) -- unification between a type and a fully applied type function; CEq t f: t ~ f | ||
166 | -- TODO: merge with CUnify? | ||
167 | | CUnify_ b b -- unification between (non-type-function) types; CUnify t s: t ~ s | ||
168 | | Split_ b b b -- Split x y z: x, y, z are records; fields of x = disjoint union of the fields of y and z | ||
169 | |||
170 | | ETypeSig_ b b | ||
171 | | Case_ b b [(p {-Name, [Name{-v-}]-}, b)] -- simple case expression, not used yet | ||
172 | | WhereBlock_ [(Name{-v-}, b)] b -- not used yet | ||
173 | | PrimFun b Name [b] Int -- type, name, collected args, arity | ||
174 | | FunAlts_ Int{-number of parameters-} [([ParPat b], GuardTree b)] | ||
175 | -- TODO: remove | ||
176 | | EAlts_ [b] -- function alternatives | ||
177 | | ENext_ Doc b -- go to next alternative | ||
178 | |||
179 | deriving (Eq,Ord,Functor,Foldable,Traversable) -- TODO: elim Eq instance | ||
180 | |||
181 | -- TODO! remove | ||
182 | instance Eq Doc where _ == _ = True | ||
183 | instance Ord Doc where _ `compare` _ = EQ | ||
184 | |||
185 | type ParPat e = [Pat' e] | ||
186 | |||
187 | data ConName | ||
188 | = TupleName Int | ||
189 | | ConName Name | ||
190 | -- | ConLit Lit | ||
191 | deriving (Eq, Ord) | ||
192 | |||
193 | data Pat' e | ||
194 | = PatVar Name -- v | ||
195 | | PatCon ConName [ParPat e] | ||
196 | | PatLit Lit | ||
197 | | ViewPat e (ParPat e) | ||
198 | | PatPrec (ParPat e) [(ParPat e{-TODO: Name-}, ParPat e)] -- used before precedence calculation | ||
199 | deriving (Eq,Ord,Functor,Foldable,Traversable) -- TODO: elim Eq instance | ||
200 | |||
201 | data GuardTree e | ||
202 | = GuardCon e ConName [ParPat e] (GuardTree e) | ||
203 | | GuardWhere (Binds e) (GuardTree e) | ||
204 | | GuardAlts [GuardTree e] | ||
205 | | GuardExp e | ||
206 | | GuardPat e (ParPat e) (GuardTree e) -- used only before precedence calculation | ||
207 | deriving (Eq,Ord,Functor,Foldable,Traversable) -- TODO: elim Eq instance | ||
208 | |||
209 | type Binds e = [(Pat, e)] -- TODO: replace with Env | ||
210 | |||
211 | data Visibility = Visible | Hidden | Irrelevant deriving (Eq, Ord) | ||
212 | |||
213 | type ExpR = Exp | ||
214 | |||
215 | pattern ExpR r e <- (peelThunkR -> (r, e)) where | ||
216 | ExpR r e = ExpTh r mempty e | ||
217 | |||
218 | expR = ExpR mempty | ||
219 | pattern EVarR' a b = ExpR a (EVar_ TWildcard b) | ||
220 | pattern EAppR' a b c = ExpR a (EApp_ TWildcard b c) | ||
221 | --pattern ELamR' a b c = ExpR a (ELam_ False b c) | ||
222 | |||
223 | pattern ExpR' a <- ExpR _ a where | ||
224 | ExpR' a = ExpR mempty a | ||
225 | |||
226 | pattern TWildcard = ExpR' TWildcard_ | ||
227 | |||
228 | data Exp = ExpTh Range Subst Exp' | ||
229 | type Exp' = Exp_ Name Pat Exp | ||
230 | |||
231 | type Ty = Exp | ||
232 | |||
233 | pattern Exp a <- (peelThunk -> a) where | ||
234 | Exp a = thunk a | ||
235 | |||
236 | thunk = ExpTh mempty{-TODO: review this-} mempty | ||
237 | |||
238 | -- TODO: eliminate or improve | ||
239 | instance Eq Exp where Exp a == Exp b = a == b | ||
240 | instance Ord Exp where Exp a `compare` Exp b = a `compare` b | ||
241 | |||
242 | pattern TCon k a <- Exp (TCon_ k (TypeIdN a)) where | ||
243 | TCon k a = Exp (TCon_ k (TypeIdN' a "typecon")) | ||
244 | |||
245 | pattern Con0 t a = TVar t (ExpN a) | ||
246 | |||
247 | pattern Star = Exp Star_ | ||
248 | |||
249 | pattern TRecord b = Exp (TRecord_ b) | ||
250 | pattern TTuple b = Exp (TTuple_ b) | ||
251 | pattern TUnit = TTuple [] | ||
252 | pattern CEq a b = Exp (CEq_ a b) | ||
253 | pattern CUnify a b = Exp (CUnify_ a b) | ||
254 | pattern Split a b c = Exp (Split_ a b c) | ||
255 | pattern Forall a b c = Exp (Forall_ Visible (Just a) b c) | ||
256 | pattern TArr a b = Exp (Forall_ Visible Nothing a b) | ||
257 | pattern ELit a = Exp (ELit_ a) | ||
258 | pattern EVar a <- Exp (EVar_ _ a) | ||
259 | pattern TVar k b = Exp (EVar_ k b) | ||
260 | pattern EApp a b <- Exp (EApp_ _ a b) | ||
261 | pattern TApp k a b = Exp (EApp_ k a b) | ||
262 | pattern ETyApp k a b = Exp (ETyApp_ k a b) | ||
263 | pattern ELam a b = Exp (ELam_ Nothing a b) | ||
264 | pattern ELet a b c = Exp (ELet_ a b c) | ||
265 | pattern ETuple a = Exp (ETuple_ a) | ||
266 | pattern ERecord b = Exp (ERecord_ b) | ||
267 | pattern EFieldProj k a = Exp (EFieldProj_ k a) | ||
268 | pattern EAlts b = Exp (EAlts_ b) | ||
269 | pattern ENext i k = Exp (ENext_ i k) | ||
270 | pattern Case t b as = Exp (Case_ t b as) | ||
271 | pattern WRefl k = Exp (WRefl_ k) | ||
272 | pattern FunAlts i as = Exp (FunAlts_ i as) | ||
273 | |||
274 | pattern A0 x <- EVar (ExpIdN x) | ||
275 | pattern A1 f x <- EApp (A0 f) x | ||
276 | pattern A2 f x y <- EApp (A1 f x) y | ||
277 | pattern A3 f x y z <- EApp (A2 f x y) z | ||
278 | pattern A4 f x y z v <- EApp (A3 f x y z) v | ||
279 | pattern A5 f x y z v w <- EApp (A4 f x y z v) w | ||
280 | pattern A6 f x y z v w q <- EApp (A5 f x y z v w) q | ||
281 | pattern A7 f x y z v w q r <- EApp (A6 f x y z v w q) r | ||
282 | pattern A8 f x y z v w q r s <- EApp (A7 f x y z v w q r) s | ||
283 | pattern A9 f x y z v w q r s t <- EApp (A8 f x y z v w q r s) t | ||
284 | pattern A10 f x y z v w q r s t a <- EApp (A9 f x y z v w q r s t) a | ||
285 | pattern A11 f x y z v w q r s t a b <- EApp (A10 f x y z v w q r s t a) b | ||
286 | |||
287 | infixr 7 ~>, ~~> | ||
288 | a ~> b = TArr a b | ||
289 | |||
290 | (~~>) :: [Exp] -> Exp -> Exp | ||
291 | args ~~> res = foldr (~>) res args | ||
292 | |||
293 | infix 4 ~~, ~~~ | ||
294 | (~~) = CEq | ||
295 | (~~~) = CUnify | ||
296 | |||
297 | buildApp :: (Exp -> Exp) -> Exp -> [Exp] -> Exp | ||
298 | buildApp n restype args = f restype $ reverse args | ||
299 | where | ||
300 | f ty [] = n ty | ||
301 | f ty (a:as) = TApp ty (f (tyOf a ~> ty) as) a | ||
302 | |||
303 | |||
304 | mapExp_ :: (PShow v, PShow p, PShow b, Ord v') => (v -> v') -> (p -> p') -> Exp_ v p b -> Exp_ v' p' b | ||
305 | mapExp_ vf f = \case | ||
306 | ELit_ x -> ELit_ x | ||
307 | EVar_ k x -> EVar_ k $ vf x | ||
308 | EApp_ k x y -> EApp_ k x y | ||
309 | ELam_ h x y -> ELam_ h (f x) y | ||
310 | ELet_ x y z -> ELet_ (f x) y z | ||
311 | ETuple_ x -> ETuple_ x | ||
312 | ERecord_ x -> ERecord_ $ x --map (vf *** id) x | ||
313 | ENamedRecord_ n x -> ENamedRecord_ n x --(vf n) $ map (vf *** id) x | ||
314 | EFieldProj_ k x -> EFieldProj_ k x -- $ vf x | ||
315 | ETypeSig_ x y -> ETypeSig_ x y | ||
316 | EAlts_ x -> EAlts_ x | ||
317 | Case_ t x xs -> Case_ t x $ map (f *** id) xs | ||
318 | ENext_ i k -> ENext_ i k | ||
319 | ETyApp_ k b t -> ETyApp_ k b t | ||
320 | PrimFun k a b c -> PrimFun k a b c | ||
321 | Star_ -> Star_ | ||
322 | TCon_ k v -> TCon_ k (vf v) | ||
323 | -- | TFun_ f [a] | ||
324 | Forall_ h mv b1 b2 -> Forall_ h (vf <$> mv) b1 b2 | ||
325 | TTuple_ bs -> TTuple_ bs | ||
326 | TRecord_ m -> TRecord_ $ Map.fromList $ map (vf *** id) $ Map.toList m -- (Map v b) | ||
327 | CEq_ a (TypeFun n as) -> CEq_ a (TypeFun (vf n) as) | ||
328 | CUnify_ a1 a2 -> CUnify_ a1 a2 | ||
329 | Split_ a1 a2 a3 -> Split_ a1 a2 a3 | ||
330 | WRefl_ k -> WRefl_ k | ||
331 | TWildcard_ -> TWildcard_ | ||
332 | EPrec_ e es -> EPrec_ e es | ||
333 | FunAlts_ i as -> FunAlts_ i as | ||
334 | x -> error $ "mapExp: " ++ ppShow x | ||
335 | |||
336 | --traverseExp :: (Applicative m, Ord v') => (v -> v') -> (t -> m t') -> Exp_ v p t -> m (Exp_ v' p t') | ||
337 | traverseExp nf f = fmap (mapExp_ nf id) . traverse f | ||
338 | |||
339 | ---------------- | ||
340 | |||
341 | data TypeFun n a = TypeFun n [a] | ||
342 | deriving (Eq,Ord,Functor,Foldable,Traversable) | ||
343 | |||
344 | type TypeFunT = TypeFun IdN Exp | ||
345 | |||
346 | -------------------------------------------------------------------------------- cached type inference | ||
347 | |||
348 | inferLit :: Lit -> Exp | ||
349 | inferLit a = thunk $ TCon_ (thunk Star_) $ flip TypeIdN' "typecon" $ case a of | ||
350 | LInt _ -> "Int" | ||
351 | LChar _ -> "Char" | ||
352 | LFloat _ -> "Float" | ||
353 | LString _ -> "String" | ||
354 | LNat _ -> "Nat" | ||
355 | |||
356 | tyFunRes :: Exp -> Exp | ||
357 | tyFunRes = \case | ||
358 | TArr a b -> b | ||
359 | x -> error $ "tyFunRes: not implemented " ++ ppShow x | ||
360 | |||
361 | tyOf :: Exp -> Exp | ||
362 | tyOf = \case | ||
363 | Exp t -> case t of | ||
364 | ELit_ l -> inferLit l | ||
365 | EVar_ k _ -> k | ||
366 | EApp_ k _ _ -> k | ||
367 | ETyApp_ k _ _ -> k | ||
368 | ETuple_ es -> TTuple $ map tyOf es | ||
369 | ELam_ (Just k) _ _ -> k | ||
370 | ELam_ Nothing (tyOfPat -> a) (tyOf -> b) -> Exp $ Forall_ Visible Nothing{-TODO-} a b | ||
371 | Case_ t _ _ -> t | ||
372 | ETypeSig_ b t -> t -- tyOf b | ||
373 | ELet_ _ _ e -> tyOf e | ||
374 | ERecord_ (unzip -> (fs, es)) -> TRecord $ Map.fromList $ zip fs $ map tyOf es | ||
375 | EFieldProj_ k _ -> k | ||
376 | EAlts_ bs -> tyOf $ head bs | ||
377 | ENext_ _ k -> k | ||
378 | PrimFun k _ _ _ -> k | ||
379 | -- was types | ||
380 | Star_ -> Star | ||
381 | TCon_ k _ -> k | ||
382 | Forall_ _ _ _ _ -> Star | ||
383 | TTuple_ _ -> Star | ||
384 | TRecord_ _ -> Star | ||
385 | CEq_ _ _ -> Star | ||
386 | CUnify_ _ _ -> Star | ||
387 | Split_ _ _ _ -> Star | ||
388 | WRefl_ k -> k | ||
389 | TWildcard_ -> TWildcard | ||
390 | e -> error $ "tyOf " ++ ppShow e | ||
391 | |||
392 | tyOfPat :: Pat -> Exp | ||
393 | tyOfPat = \case | ||
394 | PCon t _ _ -> t | ||
395 | PVar t _ -> t | ||
396 | Wildcard t -> t | ||
397 | PLit l -> inferLit l | ||
398 | PTuple xs -> thunk $ TTuple_ $ map tyOfPat xs | ||
399 | -- PRecord xs -> [(Name, b)] | ||
400 | PAt _ p -> tyOfPat p | ||
401 | e -> error $ "tyOfPat " ++ ppShow e | ||
402 | |||
403 | isStar = \case | ||
404 | Star -> True | ||
405 | _ -> False | ||
406 | |||
407 | -------------------------------------------------------------------------------- tag handling | ||
408 | |||
409 | class GetTag c where | ||
410 | type Tag c | ||
411 | getTag :: c -> Tag c | ||
412 | |||
413 | instance GetTag ExpR where | ||
414 | type Tag ExpR = Range | ||
415 | getTag (ExpR a _) = a | ||
416 | instance GetTag PatR where | ||
417 | type Tag PatR = Range | ||
418 | getTag (PatR a _) = a | ||
419 | |||
420 | -------------------------------------------------------------------------------- names | ||
421 | |||
422 | data NameSpace = TypeNS | ExpNS | ||
423 | deriving (Eq, Ord) | ||
424 | |||
425 | -- TODO: more structure instead of Doc | ||
426 | data NameInfo = NameInfo (Maybe Fixity) Doc | ||
427 | |||
428 | data N = N | ||
429 | { nameSpace :: NameSpace | ||
430 | , qualifier :: [String] | ||
431 | , nName :: String | ||
432 | , nameInfo :: NameInfo | ||
433 | } | ||
434 | |||
435 | instance Eq N where N a b c d == N a' b' c' d' = (a, b, c) == (a', b', c') | ||
436 | instance Ord N where N a b c d `compare` N a' b' c' d' = (a, b, c) `compare` (a', b', c') | ||
437 | |||
438 | type Fixity = (Maybe FixityDir, Int) | ||
439 | data FixityDir = FDLeft | FDRight | ||
440 | |||
441 | pattern ExpN n <- N ExpNS [] n _ where | ||
442 | ExpN n = N ExpNS [] n (NameInfo Nothing "exp") | ||
443 | pattern ExpN' n i = N ExpNS [] n (NameInfo Nothing i) | ||
444 | pattern TypeN n <- N TypeNS [] n _ where | ||
445 | TypeN n = N TypeNS [] n (NameInfo Nothing "type") | ||
446 | pattern TypeN' n i = N TypeNS [] n (NameInfo Nothing i) | ||
447 | |||
448 | addPrefix :: String -> Name -> Name | ||
449 | addPrefix s (N a b c d) = N a b (s ++ c) d | ||
450 | |||
451 | -- TODO: rename/eliminate | ||
452 | type Name = N | ||
453 | type TName = N | ||
454 | type TCName = N -- type constructor name; if this turns out to be slow use Int or ADT instead of String | ||
455 | type EName = N | ||
456 | type FName = N | ||
457 | type MName = N -- module name | ||
458 | type ClassName = N | ||
459 | |||
460 | toExpN (N _ a b i) = N ExpNS a b i | ||
461 | toTypeN (N _ a b i) = N TypeNS a b i | ||
462 | isTypeVar (N ns _ _ _) = ns == TypeNS | ||
463 | isConstr (N _ _ (c:_) _) = isUpper c || c == ':' | ||
464 | |||
465 | -------------------------------------------------------------------------------- error handling | ||
466 | |||
467 | -- TODO: add more structure to support desugaring | ||
468 | data Range | ||
469 | = Range SourcePos SourcePos | ||
470 | | NoRange | ||
471 | |||
472 | instance Monoid Range where | ||
473 | mempty = NoRange | ||
474 | Range a1 a2 `mappend` Range b1 b2 = Range (min a1 a2) (max b1 b2) | ||
475 | NoRange `mappend` a = a | ||
476 | a `mappend` b = a | ||
477 | |||
478 | type WithRange = (,) Range | ||
479 | pattern WithRange a b = (a, b) | ||
480 | |||
481 | -------------------------------------------------------------------------------- | ||
482 | |||
483 | type WithExplanation = (,) Doc | ||
484 | |||
485 | pattern WithExplanation d x = (d, x) | ||
486 | |||
487 | -- TODO: add more structure | ||
488 | data ErrorMsg | ||
489 | = AddRange Range ErrorMsg | ||
490 | | InFile String ErrorMsg | ||
491 | | ErrorCtx Doc ErrorMsg | ||
492 | | ErrorMsg Doc | ||
493 | | EParseError ParseError | ||
494 | | UnificationError Exp Exp [WithExplanation [Exp]] | ||
495 | |||
496 | instance Monoid ErrorMsg where | ||
497 | mempty = ErrorMsg "<<>>" | ||
498 | mappend a b = a | ||
499 | |||
500 | instance Show ErrorMsg where | ||
501 | show = show . f Nothing Nothing Nothing where | ||
502 | f d file rng = \case | ||
503 | InFile s e -> f d (Just s) Nothing e | ||
504 | AddRange NoRange e -> {- showRange file (Just r) <$$> -} f d file rng e | ||
505 | AddRange r e -> {- showRange file (Just r) <$$> -} f d file (Just r) e | ||
506 | ErrorCtx d e -> {-"during" <+> d <$$> -} f (Just d) file rng e | ||
507 | EParseError pe -> text $ show pe | ||
508 | ErrorMsg e -> maybe "" ("during" <+>) d <$$> (showRange file rng) <$$> e | ||
509 | UnificationError a b tys -> maybe "" ("during" <+>) d <$$> (showRange file rng) <$$> "cannot unify" <+> pShow a </> "with" <+> pShow b | ||
510 | <$$> "----------- equations" | ||
511 | <$$> vcat (map (\(s, l) -> s <$$> vcat (map pShow l)) tys) | ||
512 | |||
513 | dummyPos = newPos "" 0 0 | ||
514 | |||
515 | showErr :: ErrorMsg -> (SourcePos, SourcePos, String) | ||
516 | showErr e = (i, j, show msg) | ||
517 | where | ||
518 | (r, msg) = f Nothing e | ||
519 | (i, j) = case r of | ||
520 | Just (Range i j) -> (i, j) | ||
521 | _ -> (dummyPos, dummyPos) | ||
522 | f rng = \case | ||
523 | InFile s e -> f Nothing e | ||
524 | AddRange r e -> f (Just r) e | ||
525 | ErrorCtx d e -> {-(("during" <+> d) <+>) <$> -} f rng e | ||
526 | EParseError pe -> (Just $ Range p (incSourceColumn p 1), {-vcat $ map (text . messageString) $ errorMessages-} text $ show pe) | ||
527 | where p = errorPos pe | ||
528 | ErrorMsg d -> (rng, d) | ||
529 | UnificationError a b tys -> (rng, "cannot unify" <+> pShow a </> "with" <+> pShow b) | ||
530 | |||
531 | type ErrorT = ExceptT ErrorMsg | ||
532 | |||
533 | throwParseError = throwError . EParseError | ||
534 | |||
535 | mapError f m = catchError m $ throwError . f | ||
536 | |||
537 | addCtx d = mapError (ErrorCtx d) | ||
538 | |||
539 | addRange :: MonadError ErrorMsg m => Range -> m a -> m a | ||
540 | addRange NoRange = id | ||
541 | addRange r = mapError $ AddRange r | ||
542 | |||
543 | --throwErrorTCM :: Doc -> TCM a | ||
544 | throwErrorTCM = throwError . ErrorMsg | ||
545 | |||
546 | showRange :: Maybe String -> Maybe Range -> Doc | ||
547 | showRange Nothing Nothing = "no file position" | ||
548 | showRange Nothing (Just _) = "no file" | ||
549 | showRange (Just _) Nothing = "no position" | ||
550 | showRange (Just src) (Just (Range s e)) = str | ||
551 | where | ||
552 | startLine = sourceLine s - 1 | ||
553 | endline = sourceLine e - if sourceColumn e == 1 then 1 else 0 | ||
554 | len = endline - startLine | ||
555 | str = vcat $ ("position:" <+> text (show s) <+> "-" <+> text (show e)): | ||
556 | map text (take len $ drop startLine $ lines src) | ||
557 | ++ [text $ replicate (sourceColumn s - 1) ' ' ++ replicate (sourceColumn e - sourceColumn s) '^' | len == 1] | ||
558 | |||
559 | -------------------------------------------------------------------------------- parser output | ||
560 | |||
561 | data ValueDef p e = ValueDef Bool{-recursive-} p e | ||
562 | data TypeSig n t = TypeSig n t | ||
563 | |||
564 | data ModuleR | ||
565 | = Module | ||
566 | { extensions :: [Extension] | ||
567 | , moduleImports :: [Name] -- TODO | ||
568 | , moduleExports :: Maybe [Export] | ||
569 | , definitions :: [DefinitionR] | ||
570 | } | ||
571 | |||
572 | type DefinitionR = WithRange Definition | ||
573 | data Definition | ||
574 | = DValueDef Bool{-True: use in instance search-} (ValueDef PatR ExpR) | ||
575 | | DAxiom (TypeSig Name ExpR) | ||
576 | | DDataDef Name [(Name, ExpR)] [WithRange ConDef] -- TODO: remove, use GADT | ||
577 | | GADT Name [(Name, ExpR)] [WithRange (Name, ConDef')] | ||
578 | | ClassDef [ExpR] Name [(Name, ExpR)] [TypeSig Name ExpR] | ||
579 | | InstanceDef [ExpR] Name [ExpR] [ValueDef PatR ExpR] | ||
580 | | TypeFamilyDef Name [(Name, ExpR)] ExpR | ||
581 | | PrecDef Name Fixity | ||
582 | -- used only during parsing | ||
583 | | PreValueDef (Range, EName) [PatR] WhereRHS | ||
584 | | DTypeSig (TypeSig EName ExpR) | ||
585 | | ForeignDef Name ExpR | ||
586 | |||
587 | -- used only during parsing | ||
588 | data WhereRHS = WhereRHS GuardedRHS (Maybe WhereBlock) | ||
589 | type WhereBlock = [DefinitionR] | ||
590 | |||
591 | -- used only during parsing | ||
592 | data GuardedRHS | ||
593 | = Guards Range [(ExpR, ExpR)] | ||
594 | | NoGuards ExpR | ||
595 | |||
596 | data ConDef = ConDef Name [FieldTy] | ||
597 | data ConDef' = ConDef' [(Maybe Name, ExpR)] [FieldTy] ExpR | ||
598 | data FieldTy = FieldTy {fieldName :: Maybe (Name, Bool{-True: context projection-}), fieldType :: ExpR} | ||
599 | |||
600 | type TypeFunR = TypeFun Name ExpR | ||
601 | type ValueDefR = ValueDef PatR ExpR | ||
602 | |||
603 | data Extension | ||
604 | = NoImplicitPrelude | ||
605 | deriving (Eq, Ord, Show) | ||
606 | |||
607 | data Export | ||
608 | = ExportModule Name | ||
609 | | ExportId Name | ||
610 | |||
611 | -------------------------------------------------------------------------------- names with unique ids | ||
612 | |||
613 | type IdN = N | ||
614 | pattern IdN a = a | ||
615 | --newtype IdN = IdN N deriving (Eq, Ord) | ||
616 | {- TODO | ||
617 | data IdN = IdN !Int N | ||
618 | |||
619 | instance Eq IdN where IdN i _ == IdN j _ = i == j | ||
620 | instance Ord IdN where IdN i _ `compare` IdN j _ = i `compare` j | ||
621 | -} | ||
622 | |||
623 | pattern TypeIdN n <- IdN (TypeN n) | ||
624 | pattern TypeIdN' n i = IdN (TypeN' n i) | ||
625 | pattern ExpIdN n <- IdN (ExpN n) | ||
626 | pattern ExpIdN' n i = IdN (ExpN' n i) | ||
627 | |||
628 | type FreshVars = [String] -- fresh typevar names | ||
629 | |||
630 | type VarMT = StateT FreshVars | ||
631 | |||
632 | show5 :: Int -> String | ||
633 | show5 i = replicate (5 - length s) '0' ++ s where s = show i | ||
634 | |||
635 | freshTypeVars :: FreshVars | ||
636 | freshTypeVars = map ('t':) $ map show5 [0..] | ||
637 | |||
638 | resetVars :: MonadState FreshVars m => m () | ||
639 | resetVars = put freshTypeVars | ||
640 | |||
641 | newName :: MonadState FreshVars m => Doc -> m IdN | ||
642 | newName info = do | ||
643 | i <- gets head | ||
644 | modify tail | ||
645 | return $ TypeN' i info | ||
646 | |||
647 | newEName = do | ||
648 | i <- gets head | ||
649 | modify tail | ||
650 | return $ ExpN $ "e" ++ i | ||
651 | |||
652 | |||
653 | -------------------------------------------------------------------------------- environments | ||
654 | |||
655 | type Env' a = Map Name a | ||
656 | type Env a = Map IdN a | ||
657 | |||
658 | data Item = ISubst Bool{-True: found & replaced def-} Exp | ISig Bool{-True: Rigid-} Exp | ||
659 | |||
660 | tyOfItem = eitherItem (const tyOf) $ const id | ||
661 | |||
662 | eitherItem f g (ISubst r x) = f r x | ||
663 | eitherItem f g (ISig r x) = g r x | ||
664 | |||
665 | pureSubst se = null [x | ISig rigid x <- Map.elems $ getTEnv se] | ||
666 | onlySig (TEnv x) = TEnv $ Map.filter isSig x | ||
667 | isSig = eitherItem (\_ -> const False) (\rigid -> const True) | ||
668 | |||
669 | newtype Subst = Subst {getSubst :: Env Exp} | ||
670 | |||
671 | instance Monoid Subst where | ||
672 | mempty = Subst mempty | ||
673 | -- semantics: subst (m1 <> m2) = subst m1 . subst m2 | ||
674 | -- example: subst ({y -> z} <> {x -> y}) = subst {y -> z} . subst {x -> y} = subst {y -> z, x -> z} | ||
675 | -- example2: subst ({x -> z} <> {x -> y}) = subst {x -> z} . subst {x -> y} = subst {x -> y} | ||
676 | m1@(Subst y1) `mappend` Subst y2 = Subst $ (subst_ m1 <$> y2) <> y1 | ||
677 | |||
678 | subst_ = subst | ||
679 | singSubst' a b = Subst $ Map.singleton a b | ||
680 | |||
681 | nullSubst (Subst s) = Map.null s | ||
682 | toTEnv (Subst s) = TEnv $ ISubst False <$> s | ||
683 | toSubst (TEnv s) = Subst $ Map.map (\(ISubst _ e) -> e) $ Map.filter (eitherItem (\_ -> const True) (\_ -> const False)) s | ||
684 | |||
685 | newtype TEnv = TEnv {getTEnv :: Env Item} -- either substitution or bound name | ||
686 | |||
687 | instance Monoid TEnv where | ||
688 | mempty = TEnv mempty | ||
689 | -- semantics: apply (m1 <> m2) = apply m1 . apply m2 | ||
690 | -- example: subst ({y -> z} <> {x -> y}) = subst {y -> z} . subst {x -> y} = subst {y -> z, x -> z} | ||
691 | -- example2: subst ({x -> z} <> {x -> y}) = subst {x -> z} . subst {x -> y} = subst {x -> y} | ||
692 | m1@(TEnv y1) `mappend` TEnv y2 = TEnv $ Map.unionWith mergeSubsts (subst (toSubst m1) <$> y2) y1 | ||
693 | |||
694 | mergeSubsts (ISubst _ s) (ISig _ _) = ISubst True s | ||
695 | mergeSubsts (ISubst b s) (ISubst b' _) = ISubst (b || b') s | ||
696 | mergeSubsts (ISig _ _) (ISubst _ s) = ISubst True s | ||
697 | mergeSubsts a _ = a | ||
698 | |||
699 | singSubst a b = TEnv $ Map.singleton a $ ISubst False b | ||
700 | singSubstTy_ a b = TEnv $ Map.singleton a $ ISig False b | ||
701 | |||
702 | -- build recursive environment -- TODO: generalize | ||
703 | recEnv :: Pat -> Exp -> Exp | ||
704 | recEnv (PVar _ v) th_ = th where th = subst (singSubst' v th) th_ | ||
705 | recEnv _ th = th | ||
706 | |||
707 | mapExp' f nf pf e = mapExp_ nf pf $ f <$> e | ||
708 | |||
709 | peelThunkR :: Exp -> (Range, Exp') | ||
710 | peelThunkR e@(ExpTh r _ _) = (r, peelThunk e) | ||
711 | |||
712 | peelThunk :: Exp -> Exp' | ||
713 | peelThunk (ExpTh _ env@(Subst m) e) | ||
714 | -- | Map.null m = e | ||
715 | | otherwise = case e of | ||
716 | Forall_ h (Just n) a b -> Forall_ h (Just n) (f a) $ subst_ (delEnv n (f a) env) b | ||
717 | ELam_ h x y -> ELam_ (f <$> h) (mapPat' x) $ subst_ (delEnvs (patternVars x) env) y | ||
718 | Case_ t e cs -> Case_ (f t) (f e) [(mapPat' x, subst_ (delEnvs (patternVars x) env) y) | (x, y) <- cs] | ||
719 | ELet_ x y z -> ELet_ (mapPat' x) (g y) (g z) where | ||
720 | g = subst_ (delEnvs (patternVars x) env) | ||
721 | EVar_ k v -> case Map.lookup v m of | ||
722 | Just e -> case peelThunk e of | ||
723 | PrimFun _ a b c -> PrimFun (f k) a b c -- hack! | ||
724 | x -> x | ||
725 | _ -> EVar_ (f k) v | ||
726 | FunAlts_ i ts -> FunAlts_ i $ flip map ts $ \(p, t) -> (p, subst (delEnvs' (foldMap patternVars' p) env) t) | ||
727 | _ -> mapExp' f id (error "peelT") e | ||
728 | where | ||
729 | f = subst_ env | ||
730 | |||
731 | mapPat' :: Pat -> Pat | ||
732 | mapPat' (Pat p) = Pat $ mapPat f id id $ mapPat' <$> p | ||
733 | |||
734 | delEnv n x = delEnvs [(n, x)] | ||
735 | |||
736 | delEnvs xs (Subst env) = Subst $ foldr Map.delete env $ map fst xs | ||
737 | delEnvs' xs (Subst env) = Subst $ foldr Map.delete env xs | ||
738 | |||
739 | subst1 :: Subst -> Exp -> Exp | ||
740 | subst1 s@(Subst m) = \case | ||
741 | TVar k v -> case Map.lookup v m of | ||
742 | Just e -> subst1 s e | ||
743 | _ -> TVar k v | ||
744 | e -> e | ||
745 | |||
746 | -------------------------------------------------------------------------------- | ||
747 | -- fix :: forall (a :: *) . (a -> a) -> a | ||
748 | -- fix = \{a :: *} (f :: a -> a) -> [ x |-> f x ] x :: a | ||
749 | |||
750 | fixName = ExpN "fix" | ||
751 | |||
752 | fixBody :: Exp | ||
753 | fixBody = Exp $ ELam_ (Just ty) (PVar Star an) $ Exp $ ELam_ Nothing (PVar a fn) fx | ||
754 | where | ||
755 | ty = Exp $ Forall_ Hidden (Just an) Star $ (a ~> a) ~> a | ||
756 | |||
757 | fx = ExpTh mempty{-TODO: review this-} (singSubst' x $ TApp a f fx) $ EVar_ a x | ||
758 | |||
759 | an = TypeN "a" | ||
760 | a = TVar Star an | ||
761 | fn = ExpN "f" | ||
762 | f = TVar (a ~> a) fn | ||
763 | x = ExpN "x" | ||
764 | |||
765 | -------------------------------------------------------------------------------- | ||
766 | |||
767 | data PolyEnv = PolyEnv | ||
768 | { instanceDefs :: InstanceDefs | ||
769 | , getPolyEnv :: Env' Item | ||
770 | , constructors :: Env' [(Name, Int)] | ||
771 | , precedences :: PrecMap | ||
772 | , typeFamilies :: InstEnv | ||
773 | , infos :: Infos | ||
774 | } | ||
775 | |||
776 | type Info = (SourcePos, SourcePos, String) | ||
777 | type Infos = [Info] | ||
778 | |||
779 | type InstEnv = Env' Exp | ||
780 | |||
781 | type PrecMap = Env' Fixity | ||
782 | |||
783 | type InstanceDefs = Env' (Map Name ()) | ||
784 | |||
785 | emptyPolyEnv :: PolyEnv | ||
786 | emptyPolyEnv = PolyEnv mempty mempty mempty mempty mempty mempty | ||
787 | |||
788 | startPolyEnv = emptyPolyEnv {getPolyEnv = Map.singleton fixName $ ISubst True fixBody} | ||
789 | |||
790 | joinPolyEnvs :: forall m. MonadError ErrorMsg m => Bool -> [PolyEnv] -> m PolyEnv | ||
791 | joinPolyEnvs allownameshadow ps = PolyEnv | ||
792 | <$> mkJoin' instanceDefs | ||
793 | <*> mkJoin allownameshadow getPolyEnv | ||
794 | <*> mkJoin allownameshadow constructors | ||
795 | <*> mkJoin False precedences | ||
796 | <*> mkJoin False typeFamilies | ||
797 | <*> pure (concatMap infos ps) | ||
798 | where | ||
799 | mkJoin :: Bool -> (PolyEnv -> Env a) -> m (Env a) | ||
800 | mkJoin True f = return $ Map.unions $ map f ps | ||
801 | mkJoin False f = case filter (not . Map.null) . map f $ ps of | ||
802 | [m] -> return m | ||
803 | ms -> case filter (not . null . drop 1 . snd) $ Map.toList ms' of | ||
804 | [] -> return $ fmap head $ Map.filter (not . null) ms' | ||
805 | xs -> throwErrorTCM $ "Definition clash:" <+> pShow (map fst xs) | ||
806 | where | ||
807 | ms' = Map.unionsWith (++) $ map ((:[]) <$>) ms | ||
808 | |||
809 | mkJoin' f = case [(n, x) | (n, s) <- Map.toList ms', (x, is) <- Map.toList s, not $ null $ drop 1 is] of | ||
810 | _ -> return $ fmap head . Map.filter (not . null) <$> ms' | ||
811 | -- xs -> throwErrorTCM $ "Definition clash':" <+> pShow xs | ||
812 | where | ||
813 | ms' = Map.unionsWith (Map.unionWith (++)) $ map ((((:[]) <$>) <$>) . f) ps | ||
814 | |||
815 | addPolyEnv pe m = do | ||
816 | env <- ask | ||
817 | env <- joinPolyEnvs True [pe, env] | ||
818 | local (const env) m | ||
819 | |||
820 | -- reversed order! | ||
821 | getApp (Exp x) = case x of | ||
822 | EApp_ _ f x -> (id *** (x:)) <$> getApp f | ||
823 | TCon_ _ n -> Just (n, []) | ||
824 | _ -> Nothing | ||
825 | |||
826 | withTyping ts = addPolyEnv $ emptyPolyEnv {getPolyEnv = ISig False <$> ts} | ||
827 | |||
828 | -------------------------------------------------------------------------------- monads | ||
829 | |||
830 | nullTEnv (TEnv m) = Map.null m | ||
831 | |||
832 | type TypingT = WriterT' TEnv | ||
833 | |||
834 | type EnvType = (TEnv, Exp) | ||
835 | |||
836 | hidden = \case | ||
837 | Visible -> False | ||
838 | _ -> True | ||
839 | |||
840 | toEnvType :: Exp -> ([(Visibility, (Name, Exp))], Exp) | ||
841 | toEnvType = \case | ||
842 | Exp (Forall_ v@(hidden -> True) (Just n) t x) -> ((v, (n, t)):) *** id $ toEnvType x | ||
843 | x -> (mempty, x) | ||
844 | |||
845 | envType d = TEnv $ Map.fromList $ map ((id *** ISig False) . snd) d | ||
846 | |||
847 | addInstance n ((envType *** id) . toEnvType -> (_, getApp -> Just (c, _))) | ||
848 | = addPolyEnv $ emptyPolyEnv {instanceDefs = Map.singleton c $ Map.singleton n ()} | ||
849 | |||
850 | monoInstType v k = Map.singleton v k | ||
851 | |||
852 | toTCMS :: Exp -> TCMS ([Exp], Exp) | ||
853 | toTCMS (toEnvType -> (typ@(envType -> TEnv se), ty)) = WriterT' $ do | ||
854 | let fv = map (fst . snd) typ | ||
855 | newVars <- forM fv $ \case | ||
856 | TypeN' n i -> newName $ "instvar" <+> text n <+> i | ||
857 | v -> error $ "instT: " ++ ppShow v | ||
858 | let s = Map.fromList $ zip fv newVars | ||
859 | return (TEnv $ repl s se, (map (repl s . uncurry (flip TVar)) $ hiddenVars typ, repl s ty)) | ||
860 | |||
861 | hiddenVars ty = [x | (Hidden, x) <- ty] | ||
862 | |||
863 | instantiateTyping_ vis info se ty = do | ||
864 | ambiguityCheck ("ambcheck" <+> info) se ty --(subst su se) (subst su ty) | ||
865 | typingToTy_ vis ".." (se, ty) | ||
866 | where | ||
867 | su = toSubst se | ||
868 | |||
869 | splitEnv (TEnv se) = TEnv *** TEnv $ cycle (f gr') (se', gr') | ||
870 | where | ||
871 | (se', gr') = flip Map.partition se $ \case | ||
872 | ISubst False _ -> False | ||
873 | _ -> True | ||
874 | f = foldMap (\(k, ISubst False x) -> Set.insert k $ freeVars x) . Map.toList | ||
875 | f' = foldMap (\(k, ISig False x) -> Set.insert k $ freeVars x) . Map.toList | ||
876 | cycle acc (se, gr) = (if Set.null s then id else cycle (acc <> s)) (se', gr <> gr') | ||
877 | where | ||
878 | (se', gr') = flip Map.partitionWithKey se $ \k -> \case | ||
879 | ISig False t -> not $ Set.insert k (freeVars t) `hasSame` acc | ||
880 | _ -> True | ||
881 | s = f' gr' | ||
882 | |||
883 | hasSame a b = not $ Set.null $ a `Set.intersection` b | ||
884 | |||
885 | instantiateTyping_' :: Bool -> Doc -> TEnv -> Exp -> TCM ([(IdN, Exp)], Exp) | ||
886 | instantiateTyping_' typ info se ty = do | ||
887 | ty <- instantiateTyping_ (if typ then Hidden else Irrelevant) info se ty | ||
888 | return (hiddenVars $ fst $ toEnvType ty, ty) | ||
889 | |||
890 | -- Ambiguous: (Int ~ F a) => Int | ||
891 | -- Not ambiguous: (Show a, a ~ F b) => b | ||
892 | --ambiguityCheck :: Doc -> TCMS Exp -> TCMS Exp | ||
893 | ambiguityCheck msg se ty = do | ||
894 | pe <- asks getPolyEnv | ||
895 | let defined = dependentVars (Map.toList $ getTEnv se) $ Map.keysSet pe <> freeVars ty | ||
896 | case [(n, c) | (n, ISig rigid c) <- Map.toList $ getTEnv se, not $ any (`Set.member` defined) $ Set.insert n $ freeVars c] of | ||
897 | [] -> return () | ||
898 | err -> do | ||
899 | tt <- typingToTy' (se, ty) | ||
900 | throwErrorTCM $ | ||
901 | "during" <+> msg </> "ambiguous type:" <$$> pShow tt <$$> "problematic vars:" <+> pShow err | ||
902 | |||
903 | -- compute dependent type vars in constraints | ||
904 | -- Example: dependentVars [(a, b) ~ F b c, d ~ F e] [c] == [a,b,c] | ||
905 | dependentVars :: [(IdN, Item)] -> Set TName -> Set TName | ||
906 | dependentVars ie s = cycle mempty s | ||
907 | where | ||
908 | cycle acc s | ||
909 | | Set.null s = acc | ||
910 | | otherwise = cycle (acc <> s) (grow s Set.\\ acc) | ||
911 | |||
912 | grow = flip foldMap ie $ \case | ||
913 | (n, ISig rigid t) -> (Set.singleton n <-> freeVars t) <> case t of | ||
914 | CEq ty f -> freeVars ty <-> freeVars f | ||
915 | Split a b c -> freeVars a <-> (freeVars b <> freeVars c) | ||
916 | -- CUnify{} -> mempty --error "dependentVars: impossible" | ||
917 | _ -> mempty | ||
918 | -- (n, ISubst False x) -> (Set.singleton n <-> freeVars x) | ||
919 | _ -> mempty | ||
920 | where | ||
921 | a --> b = \s -> if Set.null $ a `Set.intersection` s then mempty else b | ||
922 | a <-> b = (a --> b) <> (b --> a) | ||
923 | |||
924 | --typingToTy' :: EnvType -> Exp | ||
925 | typingToTy' (s, t) = typingToTy "typingToTy" s t | ||
926 | |||
927 | --typingToTy :: Doc -> TEnv -> Exp -> Exp | ||
928 | typingToTy msg env ty = removeStar . renameVars <$> typingToTy_ Hidden msg (env, ty) | ||
929 | where | ||
930 | removeStar (Exp (Forall_ (hidden -> True) _ Star t)) = removeStar t | ||
931 | removeStar t = t | ||
932 | |||
933 | renameVars :: Exp -> Exp | ||
934 | renameVars = flip evalState (map (:[]) ['a'..]) . f mempty | ||
935 | where | ||
936 | f m (Exp e) = Exp <$> case e of | ||
937 | Forall_ h (Just n) k e -> do | ||
938 | n' <- gets (TypeN . head) | ||
939 | modify tail | ||
940 | Forall_ h (Just n') <$> f m k <*> f (Map.insert n n' m) e | ||
941 | e -> traverseExp nf (f m) e | ||
942 | where | ||
943 | nf n = fromMaybe n $ Map.lookup n m | ||
944 | |||
945 | --typingToTy_ :: Visibility -> Doc -> EnvType -> Exp | ||
946 | typingToTy_ vs msg (env, ty) = do | ||
947 | pe <- asks getPolyEnv | ||
948 | return $ f (Map.keysSet pe) l | ||
949 | where | ||
950 | l = sortBy (compare `on` constrKind . snd) [(n, t) | (n, ISig rigid t) <- Map.toList $ getTEnv env] | ||
951 | forall_ n k t | ||
952 | -- | n `Set.notMember` freeVars t = TArrH k t | ||
953 | | otherwise = Exp $ Forall_ vs (Just n) k t | ||
954 | |||
955 | constrKind = \case | ||
956 | Star -> 0 | ||
957 | _ -> 2 | ||
958 | |||
959 | -- TODO: make more efficient? | ||
960 | f s [] = ty | ||
961 | f s ts = case [x | x@((n, t), ts') <- getOne ts, let fv = freeVars t, fv `Set.isSubsetOf` s] of | ||
962 | (((n, t), ts): _) -> forall_ n t $ f (Set.insert n s) ts | ||
963 | _ -> error $ show $ "orderEnv:" <+> msg <$$> pShow ts <$$> pShow l <$$> pShow ty | ||
964 | |||
965 | getOne xs = [(b, a ++ c) | (a, b: c) <- zip (inits xs) (tails xs)] | ||
966 | |||
967 | instance PShow Subst where | ||
968 | pShowPrec p (Subst t) = "Subst" <+> pShow t | ||
969 | |||
970 | -- type checking monad transformer | ||
971 | type TCMT m = ReaderT PolyEnv (ErrorT (WriterT Infos (VarMT m))) | ||
972 | |||
973 | type TCM = TCMT Identity | ||
974 | |||
975 | type TCMS = TypingT TCM | ||
976 | |||
977 | catchExc :: TCM a -> TCM (Maybe a) | ||
978 | catchExc = mapReaderT $ lift . fmap (either (const Nothing) Just) . runExceptT | ||
979 | |||
980 | -------------------------------------------------------------------------------- free variables | ||
981 | |||
982 | class FreeVars a where freeVars :: a -> Set IdN | ||
983 | |||
984 | instance FreeVars Exp where | ||
985 | freeVars = \case | ||
986 | Exp x -> case x of | ||
987 | ELam_ h x y -> freeVars y Set.\\ Set.fromList (map fst $ patternVars x) -- TODO: h? | ||
988 | Case_ t e cs -> freeVars t <> freeVars e <> foldMap (\(x, y) -> freeVars y Set.\\ Set.fromList (map fst $ patternVars x)) cs | ||
989 | ELet_ x y z -> (freeVars y <> freeVars z) Set.\\ Set.fromList (map fst $ patternVars x) -- TODO: revise | ||
990 | EVar_ k a -> Set.singleton a <> freeVars k | ||
991 | Forall_ h (Just v) k t -> freeVars k <> Set.delete v (freeVars t) | ||
992 | x -> foldMap freeVars x | ||
993 | |||
994 | instance FreeVars a => FreeVars [a] where freeVars = foldMap freeVars | ||
995 | instance FreeVars a => FreeVars (TypeFun n a) where freeVars = foldMap freeVars | ||
996 | instance FreeVars a => FreeVars (Env a) where freeVars = foldMap freeVars | ||
997 | |||
998 | -------------------------------------------------------------------------------- replacement | ||
999 | |||
1000 | type Repl = Map IdN IdN | ||
1001 | |||
1002 | -- TODO: express with Substitute? | ||
1003 | class Replace a where repl :: Repl -> a -> a | ||
1004 | |||
1005 | -- TODO: make more efficient | ||
1006 | instance Replace Exp where | ||
1007 | repl st = \case | ||
1008 | ty | Map.null st -> ty -- optimization | ||
1009 | Exp s -> Exp $ case s of | ||
1010 | ELam_ h _ _ -> error "repl lam" | ||
1011 | Case_ _ _ _ -> error "repl case" | ||
1012 | ELet_ _ _ _ -> error "repl let" | ||
1013 | Forall_ h (Just n) a b -> Forall_ h (Just n) (f a) (repl (Map.delete n st) b) | ||
1014 | t -> mapExp' f rn (error "repl") t | ||
1015 | where | ||
1016 | f = repl st | ||
1017 | rn a | ||
1018 | | Just t <- Map.lookup a st = t | ||
1019 | | otherwise = a | ||
1020 | |||
1021 | instance Replace a => Replace (Env a) where | ||
1022 | repl st e = Map.fromList $ map (r *** repl st) $ Map.toList e | ||
1023 | where | ||
1024 | r x = fromMaybe x $ Map.lookup x st | ||
1025 | |||
1026 | instance (Replace a, Replace b) => Replace (Either a b) where | ||
1027 | repl st = either (Left . repl st) (Right . repl st) | ||
1028 | instance Replace Item where | ||
1029 | repl st = eitherItem (\r -> ISubst r . repl st) (\r -> ISig r . repl st) | ||
1030 | |||
1031 | -------------------------------------------------------------------------------- substitution | ||
1032 | |||
1033 | -- TODO: review usage (use only after unification) | ||
1034 | class Substitute x a where subst :: x -> a -> a | ||
1035 | |||
1036 | --instance Substitute a => Substitute (Constraint' n a) where subst = fmap . subst | ||
1037 | instance Substitute x a => Substitute x [a] where subst = fmap . subst | ||
1038 | instance (Substitute x a, Substitute x b) => Substitute x (a, b) where subst s (a, b) = (subst s a, subst s b) | ||
1039 | instance (Substitute x a, Substitute x b) => Substitute x (Either a b) where subst s = subst s +++ subst s | ||
1040 | instance Substitute x Exp => Substitute x Item where subst s = eitherItem (\r -> ISubst r . subst s) (\r -> ISig r . subst s) | ||
1041 | {- | ||
1042 | instance Substitute Pat where | ||
1043 | subst s = \case | ||
1044 | PVar t v -> PVar $ subst s v | ||
1045 | PCon t n l -> PCon (VarE n $ subst s ty) $ subst s l | ||
1046 | Pat p -> Pat $ subst s <$> p | ||
1047 | -} | ||
1048 | --instance Substitute TEnv Exp where subst = subst . toSubst --m1 (ExpTh m exp) = ExpTh (toSubst m1 <> m) exp | ||
1049 | instance Substitute Subst Exp where subst m1 (ExpTh r m exp) = ExpTh r (m1 <> m) exp | ||
1050 | --instance Substitute TEnv TEnv where subst s (TEnv m) = TEnv $ subst s <$> m | ||
1051 | instance Substitute Subst TEnv where subst s (TEnv m) = TEnv $ subst s <$> m | ||
1052 | {- | ||
1053 | instance Substitute Subst (Pat' Exp) where | ||
1054 | subst s = \case | ||
1055 | = PatVar v ->Name -- v | ||
1056 | | PatCon ConName [ParPat e] | ||
1057 | | PatLit Lit | ||
1058 | | ViewPat e (ParPat e) | ||
1059 | | PatPrec (ParPat e) [(ParPat e{-TODO-}, ParPat e)] -- used before precedence calculation | ||
1060 | x -> fmap (subst s) x | ||
1061 | -} | ||
1062 | instance Substitute Subst (GuardTree Exp) where | ||
1063 | subst s = \case | ||
1064 | GuardPat e p t -> GuardPat e p $ subst (delEnvs' (patternVars' p) s) t | ||
1065 | GuardCon e n ps t -> GuardCon e n ps $ subst (delEnvs' (foldMap patternVars' ps) s) t | ||
1066 | GuardWhere bs t -> GuardWhere (map (id *** subst s') bs) $ subst s' t | ||
1067 | where s' = delEnvs (foldMap patternVars $ map fst bs) s | ||
1068 | x -> fmap (subst s) x | ||
1069 | |||
1070 | -------------------------------------------------------------------------------- LambdaCube specific definitions | ||
1071 | -- TODO: eliminate most of these | ||
1072 | pattern StarStar = TArr Star Star | ||
1073 | |||
1074 | pattern TCon0 a = TCon Star a | ||
1075 | pattern TCon1 a b = TApp Star (TCon StarStar a) b | ||
1076 | pattern TCon2 a b c = TApp Star (TApp StarStar (TCon (TArr Star StarStar) a) b) c | ||
1077 | pattern TCon2' a b c = TApp Star (TApp StarStar (TCon VecKind a) b) c | ||
1078 | pattern TCon3' a b c d = TApp Star (TApp StarStar (TApp VecKind (TCon (TArr Star VecKind) a) b) c) d | ||
1079 | |||
1080 | pattern TVec a b = TCon2' "Vec" (ENat a) b | ||
1081 | pattern TMat a b c = TApp Star (TApp StarStar (TApp VecKind (TCon MatKind "Mat") (ENat a)) (ENat b)) c | ||
1082 | pattern TSingRecord x t <- TRecord (singletonView -> Just (x, t)) | ||
1083 | singletonView m = case Map.toList m of | ||
1084 | [a] -> Just a | ||
1085 | _ -> Nothing | ||
1086 | |||
1087 | -- basic types | ||
1088 | pattern TChar = TCon0 "Char" | ||
1089 | pattern TString = TCon0 "String" | ||
1090 | pattern TBool = TCon0 "Bool" | ||
1091 | pattern TOrdering = TCon0 "Ordering" | ||
1092 | pattern TWord = TCon0 "Word" | ||
1093 | pattern TInt = TCon0 "Int" | ||
1094 | pattern TNat = TCon0 "Nat" | ||
1095 | pattern TFloat = TCon0 "Float" | ||
1096 | pattern VecKind = TArr TNat StarStar | ||
1097 | pattern MatKind = TArr TNat (TArr TNat StarStar) | ||
1098 | pattern TList a = TCon1 "List" a | ||
1099 | |||
1100 | pattern Ordering = TCon0 "Ordering" | ||
1101 | |||
1102 | -- Semantic | ||
1103 | pattern Depth a = TCon1 "Depth" a | ||
1104 | pattern Stencil a = TCon1 "Stencil" a | ||
1105 | pattern Color a = TCon1 "Color" a | ||
1106 | |||
1107 | -- GADT | ||
1108 | pattern TFragmentOperation b = TCon1 "FragmentOperation" b | ||
1109 | pattern TImage b c = TCon2' "Image" b c | ||
1110 | pattern TInterpolated b = TCon1 "Interpolated" b | ||
1111 | pattern TFrameBuffer b c = TCon2' "FrameBuffer" b c | ||
1112 | pattern TSampler = TCon0 "Sampler" | ||
1113 | |||
1114 | pattern ClassN n <- TypeN n where | ||
1115 | ClassN n = TypeN' n "class" | ||
1116 | pattern IsValidOutput = ClassN "ValidOutput" | ||
1117 | pattern IsTypeLevelNatural = ClassN "TNat" | ||
1118 | pattern IsValidFrameBuffer = ClassN "ValidFrameBuffer" | ||
1119 | pattern IsAttributeTuple = ClassN "AttributeTuple" | ||
1120 | |||
1121 | pattern TypeFunS a b <- TypeFun (TypeN a) b where | ||
1122 | TypeFunS a b = TypeFun (TypeN' a "typefun") b | ||
1123 | pattern TFMat a b = TypeFunS "TFMat" [a, b] -- may be data family | ||
1124 | pattern TFVec a b = TypeFunS "TFVec" [a, b] -- may be data family | ||
1125 | pattern TFMatVecElem a = TypeFunS "MatVecElem" [a] | ||
1126 | pattern TFMatVecScalarElem a = TypeFunS "MatVecScalarElem" [a] | ||
1127 | pattern TFVecScalar a b = TypeFunS "VecScalar" [a, b] | ||
1128 | pattern TFFTRepr' a = TypeFunS "FTRepr'" [a] | ||
1129 | pattern TFColorRepr a = TypeFunS "ColorRepr" [a] | ||
1130 | pattern TFFrameBuffer a = TypeFunS "TFFrameBuffer" [a] | ||
1131 | pattern TFFragOps a = TypeFunS "FragOps" [a] | ||
1132 | pattern TFJoinTupleType a b = TypeFunS "JoinTupleType" [a, b] | ||
1133 | |||
1134 | -------------------------------------------------------------------------------- | ||
1135 | -- reducer implemented following | ||
1136 | -- "A Tutorial Implementation of a Dependently Typed Lambda Calculus" | ||
1137 | -- Andres Löh, Conor McBride and Wouter Swierstra following | ||
1138 | |||
1139 | reduceNew :: Exp -> Exp | ||
1140 | reduceNew e = quote (tyOf e) 0 $ eEval mempty e mempty | ||
1141 | |||
1142 | vQuote = VNeutral . NGlobal | ||
1143 | qname i = ExpN $ "quote" ++ show i | ||
1144 | |||
1145 | quote :: Exp -> Int -> Value -> Exp | ||
1146 | quote ty ii VStar = Star | ||
1147 | quote ty ii (VLit i) = ELit i | ||
1148 | quote ty ii (VCCon t (TupleName _) vs) = ETuple $ zipWith (\ty x -> quote ty ii x) (tupleTypes vs t) vs | ||
1149 | quote ty ii val@(VCCon t (ConName n) vs) = mkApp t (Exp $ EVar_ t n) vs | ||
1150 | where | ||
1151 | mkApp t@(Exp (Forall_ _ _ a b)) e (x:xs) = mkApp b (Exp $ EApp_ b e $ quote a ii x) xs | ||
1152 | mkApp t e [] = e | ||
1153 | mkApp a b c = error $ "mkApp: " ++ ppShow t ++ "; " ++ show val | ||
1154 | quote ty ii (VLam_ t) = Exp $ ELam_ Nothing (PVar a n) $ quote b (ii + 1) $ t $ vQuote n where | ||
1155 | n = qname ii | ||
1156 | (a, b) = case ty of | ||
1157 | Exp (Forall_ _ _ a b) -> (a, b) | ||
1158 | TWildcard -> (TWildcard, TWildcard) | ||
1159 | _ -> error $ "quote: " ++ ppShow ty | ||
1160 | quote ty ii (VPi v f) | ||
1161 | = error $ "quote: " ++ "2" | ||
1162 | quote ty ii (VNeutral n) = neutralQuote ty ii n | ||
1163 | |||
1164 | neutralQuote :: Exp -> Int -> Neutral -> Exp | ||
1165 | neutralQuote ty ii (NGlobal v) = Exp $ EVar_ ty v | ||
1166 | neutralQuote ty ii (NQuote k) | ||
1167 | = error $ "nquote: " ++ "3" | ||
1168 | neutralQuote ty ii (NApp_ n v) | ||
1169 | = error $ "nquote: " ++ "4" | ||
1170 | neutralQuote ty ii (NCase ts x) | ||
1171 | = error $ "nquote: " ++ "5" | ||
1172 | neutralQuote ty ii val@(NPrim t n vs) = Exp $ PrimFun ty n (mkApp t vs) 0 | ||
1173 | where | ||
1174 | mkApp t@(Exp (Forall_ _ _ a b)) (x:xs) = quote a ii x: mkApp b xs | ||
1175 | mkApp t [] = [] | ||
1176 | mkApp a c = error $ "mkApp2: " ++ ppShow t ++ "; " ++ show val | ||
1177 | |||
1178 | arity :: Exp -> Int | ||
1179 | arity (Exp a) = {-trace (ppShow a) $ -} case a of | ||
1180 | Forall_ Visible _ _ b -> 1 + arity b | ||
1181 | Forall_ Hidden _ _ b -> 1 + arity b | ||
1182 | Forall_ Irrelevant _ _ b -> error "arity" --0 + arity b | ||
1183 | _ -> 0 | ||
1184 | |||
1185 | primType ty l = foldr (~>) ty $ map tyOf l | ||
1186 | tupleType es = foldr (~>) (tyOf $ ETuple es) $ map tyOf es | ||
1187 | tupleTypes xs t = f xs t where | ||
1188 | f (_: xs) (Exp (Forall_ _ _ a b)) = a: f xs b | ||
1189 | f [] (TTuple _) = [] | ||
1190 | f _ _ = error $ "tupleTypes: " ++ ppShow (xs, t) | ||
1191 | |||
1192 | eEval :: [Name] -> Exp -> Env_ -> Value | ||
1193 | eEval ne (Exp e) = case e of | ||
1194 | Star_ -> const VStar | ||
1195 | ELit_ l -> const $ VLit l | ||
1196 | EVar_ t v | isConstr v -> -- trace (show i ++ " " ++ ppShow v ++ " :: " ++ ppShow t) $ | ||
1197 | \d -> ff i id | ||
1198 | where | ||
1199 | i = arity t | ||
1200 | ff :: Int -> ([Value] -> [Value]) -> Value | ||
1201 | ff 0 acc = {- trace (ppShow (v, t)) $ -} VCCon t (ConName v) (acc []) | ||
1202 | ff i acc = VLam_ $ \x -> ff (i-1) (acc . (x:)) | ||
1203 | EVar_ _ v -> \d -> maybe (VNeutral $ NGlobal v) (d !!) $ findIndex (== v) ne | ||
1204 | TCon_ b v | ||
1205 | -> error $ "eEval" ++ "3" | ||
1206 | TWildcard_ | ||
1207 | -> error $ "eEval" ++ "4" | ||
1208 | Forall_ v m a b-- Visibility (Maybe v) b b | ||
1209 | -> error $ "eEval" ++ "5" | ||
1210 | ELam_ _ (PVar _ n) b -> \d -> VLam_ (eEval (n: ne) b . (: d)) | ||
1211 | ELam_ ty p b -> eEval ne $ Exp $ ELam_ ty (PVar (tyOfPat p) n) $ Case (tyOf b) (Exp $ EVar_ (tyOfPat p) n) [(p, b)] | ||
1212 | where n = ExpN "lamvar" | ||
1213 | EApp_ _ f x -> \d -> vapp_ (eEval ne f d) (eEval ne x d) | ||
1214 | ETyApp_ a b c-- b b b | ||
1215 | -> error $ "eEval" ++ "8" | ||
1216 | EPrec_ _ _ -- b [(b, b)] -- aux: used only before precedence calculation | ||
1217 | -> error $ "eEval" ++ "9" | ||
1218 | ELet_ p a b -> eEval ne $ Exp $ EApp_ (tyOf b) (Exp $ ELam_ Nothing p b) a -- TODO | ||
1219 | TRecord_ m -- (Map v b) | ||
1220 | -> error $ "eEval" ++ "11" | ||
1221 | ERecord_ l -- [(Name, b)] | ||
1222 | -> error $ "eEval" ++ "12" | ||
1223 | EFieldProj_ b n --b Name | ||
1224 | -> error $ "eEval" ++ "13" | ||
1225 | TTuple_ l -- [b] | ||
1226 | -> error $ "eEval" ++ "14" | ||
1227 | ETuple_ l -> \d -> VCCon (tupleType l) (TupleName $ length l) $ map ($ d) $ map (eEval ne) l | ||
1228 | ENamedRecord_ n l --Name [(Name, b)] | ||
1229 | -> error $ "eEval" ++ "16" | ||
1230 | WRefl_ b | ||
1231 | -> error $ "eEval" ++ "17" | ||
1232 | CEq_ b t -- b (TypeFun v b) | ||
1233 | -> error $ "eEval" ++ "18" | ||
1234 | CUnify_ a b-- b b | ||
1235 | -> error $ "eEval" ++ "19" | ||
1236 | Split_ a b c-- b b b | ||
1237 | -> error $ "eEval" ++ "20" | ||
1238 | ETypeSig_ a b --b b | ||
1239 | -> error $ "eEval" ++ "21" | ||
1240 | Case_ _ a l -> {-traceShow (length l) $ -} let | ||
1241 | l' = map ff l | ||
1242 | ne' ps = reverse (map fst $ foldMap patternVars ps) ++ ne | ||
1243 | ff (PCon _ c ps, x) = (ConName c, foldr llam (eEval (ne' ps) x) ps) | ||
1244 | ff (PTuple ps, x) = (TupleName $ length ps, foldr llam (eEval (reverse [n | PVar _ n <- ps] ++ ne) x) ps) | ||
1245 | in \d -> case eEval ne a d of | ||
1246 | VCCon _ con' args -> head [foldl vapp_ (x d) args | (c, x) <- l', c == con'] | ||
1247 | VNeutral n -> VNeutral $ NCase (map (id *** ($ d)) l') n | ||
1248 | x -> error $ "eEval case: " ++ ppShow x | ||
1249 | where | ||
1250 | llam :: PatR -> (Env_ -> Value) -> Env_ -> Value | ||
1251 | llam (PVar _ n) e = \d -> VLam_ (e . (: d)) | ||
1252 | llam (Wildcard _) e = e | ||
1253 | llam p e = error $ "llam: " ++ ppShow p | ||
1254 | |||
1255 | |||
1256 | WhereBlock_ l a-- [(Name{-v-}, b)] b | ||
1257 | -> error $ "eEval" ++ "23" | ||
1258 | PrimFun ty n@(ExpN s) l i -> \d -> ff i id d | ||
1259 | where | ||
1260 | l' = map (eEval ne) l | ||
1261 | ff :: Int -> ([Value] -> [Value]) -> Env_ -> Value | ||
1262 | ff 0 acc d = f s ({-reverse ??? -} (map ($ d) l') ++ acc []) | ||
1263 | ff i acc d = VLam_ $ \x -> ff (i-1) (acc . (x:)) d | ||
1264 | |||
1265 | f "primIntToFloat" [VInt i] = VFloat $ fromIntegral i | ||
1266 | f "primNegateFloat" [VFloat i] = VFloat $ negate i | ||
1267 | f "PrimSin" [VFloat i] = VFloat $ sin i | ||
1268 | f "PrimCos" [VFloat i] = VFloat $ cos i | ||
1269 | f "PrimExp" [VFloat i] = VFloat $ exp i | ||
1270 | f "PrimLog" [VFloat i] = VFloat $ log i | ||
1271 | f "PrimAbs" [VFloat i] = VFloat $ abs i | ||
1272 | f "PrimAddS" [VFloat i, VFloat j] = VFloat $ i + j | ||
1273 | f "PrimSubS" [VFloat i, VFloat j] = VFloat $ i - j | ||
1274 | f "PrimAddS" [VInt i, VInt j] = VInt $ i + j | ||
1275 | f "PrimSubS" [VInt i, VInt j] = VInt $ i - j | ||
1276 | f "PrimMulS" [VFloat i, VFloat j] = VFloat $ i * j | ||
1277 | f "PrimDivS" [VFloat i, VFloat j] = VFloat $ i / j | ||
1278 | f "PrimModS" [VInt i, VInt j] = VInt $ i `mod` j | ||
1279 | f "PrimSqrt" [VInt i] = VInt $ round $ sqrt $ fromInteger i | ||
1280 | f "PrimIfThenElse" [VTrue,t,_] = t | ||
1281 | f "PrimIfThenElse" [VFalse,_,e] = e | ||
1282 | f "PrimGreaterThan" [VFloat i, VFloat j] = vBool $ i > j | ||
1283 | f "primCompareInt" [VInt i,VInt j] = VOrdering (show $ compare i j) | ||
1284 | f "primCompareNat" [VNat i,VNat j] = VOrdering (show $ compare i j) | ||
1285 | f "primCompareFloat" [VFloat i,VFloat j] = VOrdering (show $ compare i j) | ||
1286 | f "primCompareString" [VString i,VString j] = VOrdering (show $ compare i j) | ||
1287 | |||
1288 | f s xs = VNeutral $ NPrim (primType ty l) n xs | ||
1289 | |||
1290 | FunAlts_ i l -- Int{-number of parameters-} [([ParPat b], GuardTree b)] | ||
1291 | -> error $ "eEval" ++ "25" | ||
1292 | -- TODO: remove | ||
1293 | EAlts_ l -- [b] -- function alternatives | ||
1294 | -> error $ "eEval" ++ "26" | ||
1295 | ENext_ d b --Doc b -- go to next alternative | ||
1296 | -> error $ "eEval" ++ "27" | ||
1297 | |||
1298 | -------------------------------------------------------------------------------- | ||
1299 | |||
1300 | data Value | ||
1301 | = VLam_ (Value -> Value) | ||
1302 | | VPi Value (Value -> Value) | ||
1303 | | VStar | ||
1304 | | VCCon Exp{-constructor type-} ConName [Value] | ||
1305 | -- | VCon IConName [Value] -- not used | ||
1306 | | VLit !Lit | ||
1307 | | VNeutral Neutral | ||
1308 | |||
1309 | data Neutral | ||
1310 | = NGlobal Name | ||
1311 | | NLocal Int -- not used.. | ||
1312 | | NQuote Int -- not used.. -- TODO | ||
1313 | | NApp_ Neutral Value | ||
1314 | | NCase [(ConName, Value)] Neutral | ||
1315 | | NPrim Exp PrimName [Value] | ||
1316 | |||
1317 | type Env_ = [Value] | ||
1318 | type NameEnv v = Map.Map N v | ||
1319 | |||
1320 | type PrimName = N | ||
1321 | |||
1322 | pattern VInt i = VLit (LInt i) | ||
1323 | pattern VNat i = VLit (LNat i) | ||
1324 | pattern VFloat i = VLit (LFloat i) | ||
1325 | pattern VString i = VLit (LString i) | ||
1326 | pattern VFalse = VCCon TBool (ConName (ExpN "False")) [] | ||
1327 | pattern VTrue = VCCon TBool (ConName (ExpN "True")) [] | ||
1328 | pattern VOrdering s = VCCon TOrdering (ConName (ExpN s)) [] | ||
1329 | |||
1330 | vBool False = VFalse | ||
1331 | vBool True = VTrue | ||
1332 | |||
1333 | vapp_ :: Value -> Value -> Value | ||
1334 | vapp_ (VLam_ f) v = f v | ||
1335 | vapp_ (VNeutral n) v = VNeutral (NApp_ n v) | ||
1336 | |||
1337 | ---------------------- TODO: remove | ||
1338 | |||
1339 | instance Show Lit where show = ppShow | ||
1340 | instance Show PatR where show = ppShow | ||
1341 | |||
1342 | instance PShow Value where | ||
1343 | pShowPrec p = pShowPrec p . quote TWildcard 0 | ||
1344 | |||
1345 | instance Show Value where | ||
1346 | show = ppShow . quote TWildcard 0 | ||
1347 | instance Show Neutral where | ||
1348 | show = show . VNeutral | ||
1349 | |||
1350 | instance Show N where show = ppShow | ||
1351 | |||
1352 | -------------------------------------------------------------------------------- | ||
1353 | |||
1354 | type ReduceM = ExceptT String (State Int) | ||
1355 | |||
1356 | isNext (Exp a) = case a of | ||
1357 | ENext_ _ _ -> Nothing | ||
1358 | e -> Just $ Exp e | ||
1359 | |||
1360 | e &. f = maybe e f $ isNext e | ||
1361 | e >>=. f = isNext e >>= f | ||
1362 | |||
1363 | msum' (x: xs) = fromMaybe (msum' xs) $ isNext x | ||
1364 | msum' _ = error "pattern match failure." | ||
1365 | |||
1366 | reduceFail' msg = Nothing | ||
1367 | |||
1368 | -- full reduction | ||
1369 | -- TODO! reduction under lambda needs alpha-conversion! | ||
1370 | reduce :: Exp -> Exp | ||
1371 | reduce = reduce_ False | ||
1372 | reduce_ lam e = reduceHNF_ lam e & \(Exp e) -> Exp $ case e of | ||
1373 | -- ELam_ _ (PVar _ n) (EApp (Exp f) (EVar n')) | n == n' && n `Set.notMember` freeVars (Exp f) -> f | ||
1374 | ELam_ a b c -> ELam_ (reduce_ lam <$> a) b (reduce_ True c) | ||
1375 | -- ELet_ p x e -> ELet_ p x e | ||
1376 | -- Forall_ a b c d -> Forall_ a b (reduce_ lam c) (reduce_ True d) | ||
1377 | e -> reduce_ lam <$> e | ||
1378 | |||
1379 | -- don't reduce under lambda | ||
1380 | reduce' :: Exp -> Exp | ||
1381 | reduce' e = reduceHNF e & \(Exp e) -> case e of | ||
1382 | ELam_ _ _ _ -> Exp e | ||
1383 | Forall_ a b c d -> Exp e -- TODO: reduce c? | ||
1384 | _ -> Exp $ reduce' <$> e | ||
1385 | |||
1386 | reduceHNF :: Exp -> Exp -- Left: pattern match failure | ||
1387 | reduceHNF = reduceHNF_ False | ||
1388 | |||
1389 | isSTy = \case | ||
1390 | {- | ||
1391 | TInt -> True | ||
1392 | TBool -> True | ||
1393 | TFloat -> True | ||
1394 | TVec n t -> n `elem` [2,3,4] && t `elem` [TFloat, TBool, TInt] | ||
1395 | TMat n m TFloat -> n `elem` [2,3,4] && n == m | ||
1396 | -} | ||
1397 | _ -> False | ||
1398 | |||
1399 | reduceHNF_ lam (Exp exp) = case exp of | ||
1400 | |||
1401 | ELet_ p x e | ||
1402 | | lam && isSTy (tyOf x) -> keep | ||
1403 | | otherwise -> reduceHNF $ TApp (tyOf e) (ELam p e) x | ||
1404 | |||
1405 | PrimFun k (ExpN f) acc 0 -> evalPrimFun keep id k f $ map reduceHNF (reverse acc) | ||
1406 | |||
1407 | EAlts_ (map reduceHNF -> es) -> msum' $ es ++ error ("pattern match failure: " ++ ppShow es) | ||
1408 | EApp_ _ f x -> reduceHNF f &. \(Exp f) -> case f of | ||
1409 | |||
1410 | PrimFun (TArr _ k) f acc i | ||
1411 | | i > 0 -> reduceHNF $ Exp $ PrimFun k f (x: acc) (i-1) | ||
1412 | -- | otherwise -> error $ "too much argument for primfun " ++ ppShow f ++ ": " ++ ppShow exp | ||
1413 | |||
1414 | EFieldProj_ _ fi -> reduceHNF x &. \case | ||
1415 | ERecord fs -> case [e | (fi', e) <- fs, fi' == fi] of | ||
1416 | [e] -> reduceHNF e | ||
1417 | e -> case fi of | ||
1418 | ExpN "x" -> case e of | ||
1419 | A4 "V4" x y z w -> x | ||
1420 | A3 "V3" x y z -> x | ||
1421 | A2 "V2" x y -> x | ||
1422 | _ -> keep | ||
1423 | ExpN "y" -> case e of | ||
1424 | A4 "V4" x y z w -> y | ||
1425 | A3 "V3" x y z -> y | ||
1426 | A2 "V2" x y -> y | ||
1427 | _ -> keep | ||
1428 | ExpN "z" -> case e of | ||
1429 | A4 "V4" x y z w -> z | ||
1430 | A3 "V3" x y z -> z | ||
1431 | _ -> keep | ||
1432 | ExpN "w" -> case e of | ||
1433 | A4 "V4" x y z w -> w | ||
1434 | _ -> keep | ||
1435 | _ -> keep | ||
1436 | |||
1437 | ELam_ _ p e -> bind' (pShow (p, getTag e)) (matchPattern (reduce' x) p) $ \case | ||
1438 | Just m' -> reduceHNF $ subst m' e | ||
1439 | _ -> keep | ||
1440 | _ -> keep | ||
1441 | _ -> keep | ||
1442 | where | ||
1443 | reduceHNF = reduceHNF_ lam | ||
1444 | |||
1445 | keep = Exp exp | ||
1446 | |||
1447 | bind' err e f = maybe (Exp $ ENext_ err $ tyOf keep) f e | ||
1448 | |||
1449 | -- TODO: make this more efficient (memoize reduced expressions) | ||
1450 | matchPattern :: Exp -> Pat -> Maybe (Maybe Subst) -- Left: pattern match failure; Right Nothing: can't reduce | ||
1451 | matchPattern e = \case | ||
1452 | Wildcard _ -> return $ Just mempty | ||
1453 | PLit l -> e >>=. \case | ||
1454 | ELit l' | ||
1455 | | l == l' -> return $ Just mempty | ||
1456 | | otherwise -> reduceFail' $ "literals doesn't match:" <+> pShow (l, l') | ||
1457 | _ -> return Nothing | ||
1458 | PVar _ v -> return $ Just $ singSubst' v e | ||
1459 | PTuple ps -> e >>=. \e -> case e of | ||
1460 | ETuple xs -> fmap mconcat . sequence <$> sequence (zipWith matchPattern xs ps) | ||
1461 | _ -> return Nothing | ||
1462 | PCon t c ps -> getApp [] e >>= \case | ||
1463 | Just (c', xs) | ||
1464 | | c == c' && length xs == length ps -> fmap mconcat . sequence <$> sequence (zipWith matchPattern xs ps) | ||
1465 | | otherwise -> reduceFail' $ "constructors doesn't match:" <+> pShow (c, c') | ||
1466 | _ -> return Nothing | ||
1467 | p -> error $ "matchPattern: " ++ ppShow p | ||
1468 | where | ||
1469 | getApp acc e = e >>=. \e -> case e of | ||
1470 | EApp a b -> getApp (b: acc) a | ||
1471 | EVar n | isConstr n -> return $ Just (n, acc) | ||
1472 | _ -> return Nothing | ||
1473 | |||
1474 | evalPrimFun :: Exp -> (Exp -> Exp) -> Exp -> String -> [Exp] -> Exp | ||
1475 | evalPrimFun keep red k = f where | ||
1476 | f "primIntToFloat" [EInt i] = EFloat $ fromIntegral i | ||
1477 | f "primNegateFloat" [EFloat i] = EFloat $ negate i | ||
1478 | f "PrimSin" [EFloat i] = EFloat $ sin i | ||
1479 | f "PrimCos" [EFloat i] = EFloat $ cos i | ||
1480 | f "PrimExp" [EFloat i] = EFloat $ exp i | ||
1481 | f "PrimLog" [EFloat i] = EFloat $ log i | ||
1482 | f "PrimAbs" [EFloat i] = EFloat $ abs i | ||
1483 | f "PrimAddS" [EFloat i, EFloat j] = EFloat $ i + j | ||
1484 | f "PrimSubS" [EFloat i, EFloat j] = EFloat $ i - j | ||
1485 | f "PrimSubS" [EInt i, EInt j] = EInt $ i - j | ||
1486 | f "PrimMulS" [EFloat i, EFloat j] = EFloat $ i * j | ||
1487 | f "PrimDivS" [EFloat i, EFloat j] = EFloat $ i / j | ||
1488 | f "PrimModS" [EInt i, EInt j] = EInt $ i `mod` j | ||
1489 | f "PrimSqrt" [EInt i] = EInt $ round $ sqrt $ fromInteger i | ||
1490 | f "PrimIfThenElse" [A0 "True",t,_] = red t | ||
1491 | f "PrimIfThenElse" [A0 "False",_,e] = red e | ||
1492 | f "PrimGreaterThan" [EFloat i, EFloat j] = if i > j then TVar TBool (ExpN "True") else TVar TBool (ExpN "False") | ||
1493 | f "primCompareInt" [EInt i,EInt j] = Con0 Ordering (show $ compare i j) | ||
1494 | f "primCompareNat" [ENat i,ENat j] = Con0 Ordering (show $ compare i j) | ||
1495 | f "primCompareFloat" [EFloat i,EFloat j] = Con0 Ordering (show $ compare i j) | ||
1496 | f "primCompareString" [EString i,EString j] = Con0 Ordering (show $ compare i j) | ||
1497 | f _ _ = keep | ||
1498 | |||
1499 | pattern Prim a b <- Exp (PrimFun _ (ExpN a) b 0) | ||
1500 | pattern Prim1 a b <- Prim a [b] | ||
1501 | pattern Prim2 a b c <- Prim a [c, b] | ||
1502 | pattern Prim3 a b c d <- Prim a [d, c, b] | ||
1503 | |||
1504 | -------------------------------------------------------------------------------- Pretty show instances | ||
1505 | |||
1506 | -- TODO: eliminate | ||
1507 | showN :: N -> String | ||
1508 | showN (N _ qs s _) = show $ hcat (punctuate (pShow '.') $ map text $ qs ++ [s]) | ||
1509 | |||
1510 | showVar (N q _ n (NameInfo _ i)) = pShow q <> text n <> "{" <> i <> "}" | ||
1511 | |||
1512 | instance PShow N where | ||
1513 | pShowPrec p = \case | ||
1514 | N _ qs s (NameInfo _ i) -> hcat (punctuate (pShow '.') $ map text $ qs ++ [s]) -- <> "{" <> i <> "}" | ||
1515 | |||
1516 | instance PShow NameSpace where | ||
1517 | pShowPrec p = \case | ||
1518 | TypeNS -> "'" | ||
1519 | ExpNS -> "" | ||
1520 | |||
1521 | instance Show ConName where show = ppShow | ||
1522 | instance PShow ConName where | ||
1523 | pShowPrec p = \case | ||
1524 | ConName n -> pShow n | ||
1525 | -- ConLit l -> pShow l | ||
1526 | TupleName i -> "Tuple" <> pShow i | ||
1527 | |||
1528 | --instance PShow IdN where pShowPrec p (IdN n) = pShowPrec p n | ||
1529 | |||
1530 | instance PShow Lit where | ||
1531 | pShowPrec p = \case | ||
1532 | LInt i -> pShow i | ||
1533 | LChar i -> text $ show i | ||
1534 | LString i -> text $ show i | ||
1535 | LFloat i -> pShow i | ||
1536 | LNat i -> pShow i | ||
1537 | |||
1538 | -- Exp k i -> pInfix (-2) "::" p i k | ||
1539 | instance (PShow v, PShow p, PShow b) => PShow (Exp_ v p b) where | ||
1540 | pShowPrec p = \case | ||
1541 | EPrec_ e es -> pApps p e $ concatMap (\(a, b) -> [a, b]) es | ||
1542 | ELit_ l -> pShowPrec p l | ||
1543 | EVar_ k v -> pShowPrec p v | ||
1544 | EApp_ k a b -> pApp p a b | ||
1545 | ETyApp_ k a b -> pTyApp p a b | ||
1546 | ETuple_ a -> tupled $ map pShow a | ||
1547 | ELam_ Nothing p b -> pParens True ("\\" <> pShow p </> "->" <+> pShow b) | ||
1548 | ELam_ _ p b -> pParens True ("\\" <> braces (pShow p) </> "->" <+> pShow b) | ||
1549 | ETypeSig_ b t -> pShow b </> "::" <+> pShow t | ||
1550 | ELet_ a b c -> "let" <+> pShow a </> "=" <+> pShow b </> "in" <+> pShow c | ||
1551 | ENamedRecord_ n xs -> pShow n <+> showRecord xs | ||
1552 | ERecord_ xs -> showRecord xs | ||
1553 | EFieldProj_ k n -> "." <> pShow n | ||
1554 | EAlts_ b -> braces (vcat $ punctuate (pShow ';') $ map pShow b) | ||
1555 | Case_ t x xs -> "case" <+> pShow x <+> "of" </> vcat [pShow p <+> "->" <+> pShow e | (p, e) <- xs] | ||
1556 | ENext_ info k -> "SKIP" <+> info | ||
1557 | PrimFun k a b c -> "primfun" <+> pShow a <+> pShow b <+> pShow c | ||
1558 | |||
1559 | Star_ -> "*" | ||
1560 | TCon_ k n -> pShow n | ||
1561 | Forall_ Visible Nothing a b -> pInfixr' (-1) "->" p a b | ||
1562 | Forall_ Irrelevant Nothing a b -> pInfixr' (-1) "==>" p a b | ||
1563 | Forall_ Hidden Nothing a b -> pInfixr' (-1) "=>" p a b | ||
1564 | Forall_ Visible (Just n) a b -> "forall" <+> pParens True (pShow n </> "::" <+> pShow a) <> "." <+> pShow b | ||
1565 | Forall_ Irrelevant (Just n) a b -> "forall" <+> "." <> braces (pShow n </> "::" <+> pShow a) <> "." <+> pShow b | ||
1566 | Forall_ Hidden (Just n) a b -> "forall" <+> braces (pShow n </> "::" <+> pShow a) <> "." <+> pShow b | ||
1567 | TTuple_ a -> tupled $ map pShow a | ||
1568 | TRecord_ m -> "Record" <+> showRecord (Map.toList m) | ||
1569 | CEq_ a b -> pShow a <+> "~" <+> pShow b | ||
1570 | CUnify_ a b -> pShow a <+> "~" <+> pShow b | ||
1571 | Split_ a b c -> pShow a <+> "<-" <+> "(" <> pShow b <> "," <+> pShow c <> ")" | ||
1572 | WRefl_ k -> "refl" <+> pShow k | ||
1573 | TWildcard_ -> "twildcard" | ||
1574 | FunAlts_ i as -> "alts" <+> pShow i </> vcat [hsep (map (hcat . intersperse "@" . map pShow) ps) <+> "->" <+> pShow t | (ps, t) <- as] | ||
1575 | --- Int{-number of parameters-} [([ParPat b], GuardTree b)] | ||
1576 | |||
1577 | getConstraints = \case | ||
1578 | Exp (Forall_ (hidden -> True) n c t) -> ((n, c):) *** id $ getConstraints t | ||
1579 | t -> ([], t) | ||
1580 | |||
1581 | showConstraints cs x | ||
1582 | = (case cs of [(Nothing, c)] -> pShow c; _ -> tupled (map pShow' cs)) | ||
1583 | </> "=>" <+> pShowPrec (-2) x | ||
1584 | where | ||
1585 | pShow' (Nothing, x) = pShow x | ||
1586 | pShow' (Just n, x) = pShow n <+> "::" <+> pShow x | ||
1587 | |||
1588 | instance PShow e => PShow (Pat' e) where | ||
1589 | pShowPrec p = \case | ||
1590 | PatVar v -> pShow v | ||
1591 | PatLit l -> pShow l | ||
1592 | PatCon n ps -> hsep $ pShow n: map pShow ps | ||
1593 | PatPrec p ps -> hsep $ map pShow $ p: concatMap (\(x,y) -> [x,y]) ps | ||
1594 | -- | ViewPat e (ParPat e) | ||
1595 | |||
1596 | instance PShow e => PShow (GuardTree e) where | ||
1597 | pShowPrec p = \case | ||
1598 | GuardCon e c ps t -> pShow (PatCon c ps) <+> "<-" <+> pShow e <+> "->" <+> pShow t | ||
1599 | GuardPat e p t -> pShow p <+> "<-" <+> pShow e <+> "->" <+> pShow t | ||
1600 | -- GuardWhere (Binds e) (GuardTree e) | ||
1601 | GuardAlts as -> braces $ vcat $ map pShow as | ||
1602 | GuardExp e -> pShow e | ||
1603 | |||
1604 | instance PShow Exp where | ||
1605 | pShowPrec p = \case | ||
1606 | (getConstraints -> (cs@(_:_), t)) -> showConstraints cs t | ||
1607 | t -> case getLams t of | ||
1608 | ([], Exp e) -> pShowPrec p e | ||
1609 | (ps, Exp e) -> pParens (p > 0) $ "\\" <> hsep (map (pShowPrec 10) ps) </> "->" <+> pShow e | ||
1610 | where | ||
1611 | getLams (ELam p e) = (p:) *** id $ getLams e | ||
1612 | getLams e = ([], e) | ||
1613 | |||
1614 | instance (PShow c, PShow v, PShow b) => PShow (Pat_ t c v b) where | ||
1615 | pShowPrec p = \case | ||
1616 | PLit_ l -> pShow l | ||
1617 | PVar_ t v -> pShow v | ||
1618 | PCon_ t s xs -> pApps p s xs | ||
1619 | PTuple_ a -> tupled $ map pShow a | ||
1620 | PRecord_ xs -> "Record" <+> showRecord xs | ||
1621 | PAt_ v p -> pShow v <> "@" <> pShow p | ||
1622 | Wildcard_ t -> "_" | ||
1623 | PPrec_ e es -> pApps p e $ concatMap (\(a, b) -> [a, b]) es | ||
1624 | |||
1625 | instance PShow Pat where | ||
1626 | pShowPrec p (Pat e) = pShowPrec p e | ||
1627 | |||
1628 | instance (PShow n, PShow a) => PShow (TypeFun n a) where | ||
1629 | pShowPrec p (TypeFun s xs) = pApps p s xs | ||
1630 | |||
1631 | |||
1632 | instance PShow TEnv where | ||
1633 | pShowPrec p (TEnv e) = showRecord $ Map.toList e | ||
1634 | |||
1635 | instance PShow Item where | ||
1636 | pShowPrec p = eitherItem (\r -> (("Subst" <> if r then "!" else "") <+>) . pShow) (\rigid -> (("Sig" <> if rigid then "!" else "") <+>) . pShow) | ||
1637 | |||
1638 | instance PShow Range where | ||
1639 | pShowPrec p = \case | ||
1640 | Range a b -> text (show a) <+> "--" <+> text (show b) | ||
1641 | NoRange -> "" | ||
1642 | |||
1643 | instance PShow Definition where | ||
1644 | pShowPrec p = \case | ||
1645 | DValueDef False (ValueDef False x _) -> "ValueDef" <+> pShow x | ||
1646 | DValueDef False (ValueDef rec x _) -> "ValueDef rec" <+> pShow x | ||
1647 | DValueDef True (ValueDef False x _) -> "ValueDef [instance]" <+> pShow x | ||
1648 | DAxiom (TypeSig x _) -> "axiom" <+> pShow x | ||
1649 | DDataDef n _ _ -> "data" <+> pShow n | ||
1650 | GADT n _ _ -> "gadt" <+> pShow n | ||
1651 | ClassDef _ n _ _ -> "class" <+> pShow n | ||
1652 | InstanceDef _ n _ _ -> "instance" <+> pShow n | ||
1653 | TypeFamilyDef n _ _ -> "type family" <+> pShow n | ||
1654 | -- used only during parsing | ||
1655 | PreValueDef (_, n) _ _ -> "pre valuedef" <+> pShow n | ||
1656 | DTypeSig (TypeSig n _) -> "typesig" <+> pShow n | ||
1657 | ForeignDef n _ -> "foreign" <+> pShow n | ||
1658 | PrecDef n p -> "precdef" <+> pShow n | ||
1659 | |||
1660 | instance PShow FixityDir where | ||
1661 | pShowPrec p = \case | ||
1662 | FDLeft -> "infixl" | ||
1663 | FDRight -> "infixr" | ||
1664 | |||
1665 | -------------------------------------------------------------------------------- WriterT' | ||
1666 | |||
1667 | class Monoid' e where | ||
1668 | type MonoidConstraint e :: * -> * | ||
1669 | mempty' :: e | ||
1670 | mappend' :: e -> e -> MonoidConstraint e e | ||
1671 | |||
1672 | newtype WriterT' e m a | ||
1673 | = WriterT' {runWriterT' :: m (e, a)} | ||
1674 | deriving (Functor,Foldable,Traversable) | ||
1675 | |||
1676 | instance (Monoid' e) => MonadTrans (WriterT' e) where | ||
1677 | lift m = WriterT' $ (,) mempty' <$> m | ||
1678 | |||
1679 | instance forall m e . (Monoid' e, MonoidConstraint e ~ m, Monad m) => Applicative (WriterT' e m) where | ||
1680 | pure a = WriterT' $ pure (mempty' :: e, a) | ||
1681 | a <*> b = join $ (<$> b) <$> a | ||
1682 | |||
1683 | instance (Monoid' e, MonoidConstraint e ~ m, Monad m) => Monad (WriterT' e m) where | ||
1684 | WriterT' m >>= f = WriterT' $ do | ||
1685 | (e1, a) <- m | ||
1686 | (e2, b) <- runWriterT' $ f a | ||
1687 | e <- mappend' e1 e2 | ||
1688 | return (e, b) | ||
1689 | |||
1690 | instance (Monoid' e, MonoidConstraint e ~ m, MonadReader r m) => MonadReader r (WriterT' e m) where | ||
1691 | ask = lift ask | ||
1692 | local f (WriterT' m) = WriterT' $ local f m | ||
1693 | |||
1694 | instance (Monoid' e, MonoidConstraint e ~ m, MonadWriter w m) => MonadWriter w (WriterT' e m) where | ||
1695 | tell = lift . tell | ||
1696 | listen = error "WriterT' listen" | ||
1697 | pass = error "WriterT' pass" | ||
1698 | |||
1699 | instance (Monoid' e, MonoidConstraint e ~ m, MonadState s m) => MonadState s (WriterT' e m) where | ||
1700 | state f = lift $ state f | ||
1701 | |||
1702 | instance (Monoid' e, MonoidConstraint e ~ m, MonadError err m) => MonadError err (WriterT' e m) where | ||
1703 | catchError (WriterT' m) f = WriterT' $ catchError m $ runWriterT' <$> f | ||
1704 | throwError e = lift $ throwError e | ||
1705 | |||
1706 | mapWriterT' f (WriterT' m) = WriterT' $ f m | ||
1707 | |||