]> Git — Sourcephile - haskell/symantic.git/blob - Language/LOL/Symantic/Expr/Lambda.hs
init
[haskell/symantic.git] / Language / LOL / Symantic / Expr / Lambda.hs
1 {-# LANGUAGE DefaultSignatures #-}
2 {-# LANGUAGE FlexibleContexts #-}
3 {-# LANGUAGE FlexibleInstances #-}
4 {-# LANGUAGE GADTs #-}
5 {-# LANGUAGE MultiParamTypeClasses #-}
6 {-# LANGUAGE OverloadedStrings #-}
7 {-# LANGUAGE Rank2Types #-}
8 {-# LANGUAGE ScopedTypeVariables #-}
9 {-# LANGUAGE TypeFamilies #-}
10 {-# LANGUAGE UndecidableInstances #-}
11 -- | Expression for /lambda abstraction/s
12 -- in /Higher-Order Abstract Syntax/ (HOAS).
13 module Language.LOL.Symantic.Expr.Lambda where
14
15 import Data.Proxy (Proxy(..))
16 import Data.Type.Equality ((:~:)(Refl))
17
18 import Language.LOL.Symantic.AST
19 import Language.LOL.Symantic.Type
20 import Language.LOL.Symantic.Expr.Common
21 import Language.LOL.Symantic.Repr.Dup
22 import Language.LOL.Symantic.Trans.Common
23
24 -- * Class 'Sym_Lambda'
25
26 -- | Symantic.
27 --
28 -- NOTE: argument @arg@ and result @res@ of 'Lambda'
29 -- wrapped inside 'lam': to control the calling
30 -- in the 'Repr_Host' instance.
31 --
32 -- NOTE: the default definitions supplied for:
33 -- 'app', 'inline', 'val' and 'lazy'
34 -- are there to avoid boilerplate code
35 -- when writting 'Trans' instances which
36 -- do not need to alterate those methods.
37 class (lam ~ Lambda_from_Repr repr) => Sym_Lambda lam repr where
38 -- | This type constructor is used like
39 -- the functional dependency: @repr -> lam@
40 -- (ie. knowing @repr@ one can determine @lam@)
41 -- in order to avoid to introduce a 'Proxy' @lam@
42 -- in 'let_inline', 'let_val' and 'let_lazy'.
43 --
44 -- Distinguishing between @lam@ and @repr@ is used to maintain
45 -- the universal polymorphism of @repr@ in 'Expr_from',
46 -- the downside with this however is that
47 -- to be an instance of 'Sym_Lambda' for all @lam@,
48 -- the @repr@ type of an interpreter
49 -- has to be parameterized by @lam@,
50 -- even though it does not actually need @lam@ to do its work.
51 --
52 -- Basically this means having sometimes to add a type annotation
53 -- to the interpreter call to specify @lam@.
54 type Lambda_from_Repr repr :: {-lam-}(* -> *)
55
56 -- | Lambda application.
57 app :: repr (Lambda lam arg res) -> repr arg -> repr res
58
59 -- | /Call-by-name/ lambda.
60 inline :: (repr arg -> repr res) -> repr (Lambda lam arg res)
61 -- | /Call-by-value/ lambda.
62 val :: (repr arg -> repr res) -> repr (Lambda lam arg res)
63 -- | /Call-by-need/ lambda (aka. /lazyness/): lazy shares its argument, no matter what.
64 lazy :: (repr arg -> repr res) -> repr (Lambda lam arg res)
65
66 default app :: Trans t repr => t repr (Lambda lam arg res) -> t repr arg -> t repr res
67 default inline :: Trans t repr => (t repr arg -> t repr res) -> t repr (Lambda lam arg res)
68 default val :: Trans t repr => (t repr arg -> t repr res) -> t repr (Lambda lam arg res)
69 default lazy :: Trans t repr => (t repr arg -> t repr res) -> t repr (Lambda lam arg res)
70 app f x = trans_lift $ trans_apply f `app` trans_apply x
71 inline f = trans_lift $ inline $ trans_apply . f . trans_lift
72 val f = trans_lift $ val $ trans_apply . f . trans_lift
73 lazy f = trans_lift $ lazy $ trans_apply . f . trans_lift
74
75 -- | Convenient 'inline' wrapper.
76 let_inline
77 :: Sym_Lambda lam repr
78 => repr var -> (repr var -> repr res) -> repr res
79 let_inline x y = inline y `app` x
80 -- | Convenient 'val' wrapper.
81 let_val
82 :: Sym_Lambda lam repr
83 => repr var -> (repr var -> repr res) -> repr res
84 let_val x y = val y `app` x
85 -- | Convenient 'lazy' wrapper.
86 let_lazy
87 :: Sym_Lambda lam repr
88 => repr var -> (repr var -> repr res) -> repr res
89 let_lazy x y = lazy y `app` x
90
91 infixl 5 `app`
92
93 instance -- Sym_Lambda Dup
94 ( Sym_Lambda lam r1
95 , Sym_Lambda lam r2
96 ) => Sym_Lambda lam (Dup r1 r2) where
97 type Lambda_from_Repr (Dup r1 r2) = Lambda_from_Repr r1
98 app (f1 `Dup` f2) (x1 `Dup` x2) = app f1 x1 `Dup` app f2 x2
99 inline f = dup1 (inline f) `Dup` dup2 (inline f)
100 val f = dup1 (val f) `Dup` dup2 (val f)
101 lazy f = dup1 (lazy f) `Dup` dup2 (lazy f)
102
103 -- * Type 'Expr_Lambda'
104 -- | Expression.
105 data Expr_Lambda (lam:: * -> *) (root:: *)
106 type instance Root_of_Expr (Expr_Lambda lam root) = root
107 type instance Type_of_Expr (Expr_Lambda lam root) = Type_Fun lam
108 type instance Sym_of_Expr (Expr_Lambda lam root) repr = Sym_Lambda lam repr
109 type instance Error_of_Expr ast (Expr_Lambda lam root)
110 = Error_Expr_Lambda (Error_of_Type ast (Type_Root_of_Expr root))
111 (Type_Root_of_Expr root)
112 ast
113 -- NOTE: require UndecidableInstances.
114
115 instance -- Expr_from AST Expr_Lambda
116 ( Type_from AST (Type_Root_of_Expr root)
117 , Expr_from AST root
118
119 , Type_Root_Lift (Type_Fun lam) (Type_Root_of_Expr root)
120 -- NOTE: require UndecidableInstances.
121 , Error_Type_Lift (Error_Type_Fun AST)
122 (Error_of_Type AST (Type_Root_of_Expr root))
123 -- NOTE: require UndecidableInstances.
124 , Error_Expr_Lift (Error_Expr_Lambda (Error_of_Type AST (Type_Root_of_Expr root))
125 ( Type_Root_of_Expr root)
126 AST)
127 (Error_of_Expr AST root)
128 -- NOTE: require UndecidableInstances.
129 , Error_Expr_Lift (Error_Expr AST) (Error_of_Expr AST root)
130 -- NOTE: require UndecidableInstances.
131 , Error_Expr_Unlift (Error_Expr AST) (Error_of_Expr AST root)
132 -- NOTE: require UndecidableInstances.
133
134 , Type_Unlift (Type_Fun lam) (Type_of_Expr root)
135 -- NOTE: require UndecidableInstances.
136
137 , Root_of_Expr root ~ root
138
139 , Implicit_HBool (Is_Last_Expr (Expr_Lambda lam root) root)
140 -- NOTE: require UndecidableInstances.
141 ) => Expr_from AST (Expr_Lambda lam root) where
142 expr_from _px_ex ctx ast k =
143 case ast of
144 AST "var" asts ->
145 case asts of
146 [AST name []] -> go ctx k
147 where
148 go
149 :: forall hs ret
150 . Context (Var (Type_Root_of_Expr root)) hs
151 -> ( forall h
152 . Type_Root_of_Expr root h
153 -> Forall_Repr_with_Context (Expr_Lambda lam root) hs h
154 -> Either (Error_of_Expr AST root) ret )
155 -> Either (Error_of_Expr AST root) ret
156 go c k' =
157 case c of
158 Context_Empty -> Left $ error_lambda_lift $
159 Error_Expr_Lambda_Var_unbound name ast
160 Var n ty `Context_Alt_Next` _ | n == name ->
161 k' ty $ Forall_Repr_with_Context $
162 \(repr `Context_Alt_Next` _) -> repr
163 _ `Context_Alt_Next` ctx' ->
164 go ctx' $ \ty (Forall_Repr_with_Context repr) ->
165 k' ty $ Forall_Repr_with_Context $
166 \(_ `Context_Alt_Next` c') -> repr c'
167 _ -> Left $ error_lambda_lift $
168 Error_Expr_Fun_Wrong_number_of_arguments 1 ast
169 AST "app" asts ->
170 case asts of
171 [ast_lam, ast_arg_actual] ->
172 expr_from (Proxy::Proxy root) ctx ast_lam $
173 \(ty_lam::Type_Root_of_Expr root h_lam) (Forall_Repr_with_Context lam) ->
174 expr_from (Proxy::Proxy root) ctx ast_arg_actual $
175 \(ty_arg_actual::Type_Root_of_Expr root h_arg_actual)
176 (Forall_Repr_with_Context arg_actual) ->
177 case type_unlift $ unType_Root ty_lam of
178 Just (ty_arg_expected `Type_Fun` ty_res
179 :: Type_Fun lam (Type_Root_of_Expr root) h_lam) ->
180 case ty_arg_expected `type_eq` ty_arg_actual of
181 Just Refl ->
182 k ty_res $ Forall_Repr_with_Context $
183 \c -> lam c `app` arg_actual c
184 Nothing -> Left $ error_lambda_lift $
185 Error_Expr_Fun_Argument_mismatch
186 (Exists_Type ty_arg_expected)
187 (Exists_Type ty_arg_actual) ast
188 Nothing -> Left $ error_lambda_lift $
189 Error_Expr_Lambda_Not_a_lambda ast
190 _ -> Left $ error_lambda_lift $
191 Error_Expr_Type (error_type_lift $
192 Error_Type_Fun_Wrong_number_of_arguments 2 ast) ast
193 AST "inline" asts -> lambda_from asts inline
194 AST "val" asts -> lambda_from asts val
195 AST "lazy" asts -> lambda_from asts lazy
196 AST "let_inline" asts -> let_from asts let_inline
197 AST "let_val" asts -> let_from asts let_val
198 AST "let_lazy" asts -> let_from asts let_lazy
199 _ -> Left $
200 case hbool :: HBool (Is_Last_Expr (Expr_Lambda lam root) root) of
201 HTrue -> error_expr_lift $ Error_Expr_Unsupported ast
202 HFalse -> error_expr_lift $ Error_Expr_Unsupported_here ast
203 where
204 lambda_from asts
205 (lam::forall repr arg res. Sym_Lambda lam repr
206 => (repr arg -> repr res) -> repr (Lambda lam arg res)) =
207 case asts of
208 [AST name [], ast_ty_arg, ast_body] ->
209 case type_from
210 (Proxy::Proxy (Type_Root_of_Expr root))
211 ast_ty_arg
212 (Right . Exists_Type) of
213 Left err -> Left $ error_lambda_lift $ Error_Expr_Type err ast
214 Right (Exists_Type (ty_arg::Type_Root_of_Expr root h_arg)) ->
215 expr_from (Proxy::Proxy root)
216 (Var name ty_arg `Context_Alt_Next` ctx) ast_body $
217 \(ty_res::Type_Root_of_Expr root h_res) (Forall_Repr_with_Context res) ->
218 k (ty_arg `type_fun` ty_res
219 :: Root_of_Type (Type_Root_of_Expr root)
220 (Lambda lam h_arg h_res)) $
221 Forall_Repr_with_Context $
222 \c -> lam $
223 \arg -> res (arg `Context_Alt_Next` c)
224 _ -> Left $ error_lambda_lift $
225 Error_Expr_Fun_Wrong_number_of_arguments 3 ast
226 let_from asts
227 (let_::forall repr var res. Sym_Lambda lam repr
228 => repr var -> (repr var -> repr res) -> repr res) =
229 case asts of
230 [AST name [], ast_var, ast_body] ->
231 expr_from (Proxy::Proxy root) ctx ast_var $
232 \(ty_var::Type_Root_of_Expr root h_var) (Forall_Repr_with_Context var) ->
233 expr_from (Proxy::Proxy root)
234 (Var name ty_var `Context_Alt_Next` ctx) ast_body $
235 \(ty_res::Type_Root_of_Expr root h_res) (Forall_Repr_with_Context res) ->
236 k ty_res $ Forall_Repr_with_Context $
237 \c -> let_ (var c) $
238 \arg -> res (arg `Context_Alt_Next` c)
239 _ -> Left $ error_lambda_lift $
240 Error_Expr_Fun_Wrong_number_of_arguments 3 ast
241 error_lambda_lift
242 :: Error_Expr_Lambda (Error_of_Type AST (Type_Root_of_Expr root)) (Type_Root_of_Expr root) AST
243 -> Error_of_Expr AST root
244 error_lambda_lift = error_expr_lift
245
246 -- * Type 'Error_Expr_Lambda'
247 data Error_Expr_Lambda err_ty ty ast
248 = Error_Expr_Lambda_Not_a_lambda ast
249 | Error_Expr_Lambda_Var_unbound Var_Name ast
250 | Error_Expr_Fun_Wrong_number_of_arguments Int ast
251 | Error_Expr_Fun_Argument_mismatch (Exists_Type ty) (Exists_Type ty) ast
252 | Error_Expr_Type err_ty ast
253 deriving (Eq, Show)