]> Git — Sourcephile - haskell/symantic.git/blob - Language/Symantic/Expr/Lambda.hs
Eq, Ord
[haskell/symantic.git] / Language / Symantic / Expr / Lambda.hs
1 {-# LANGUAGE DefaultSignatures #-}
2 {-# LANGUAGE DataKinds #-}
3 {-# LANGUAGE FlexibleContexts #-}
4 {-# LANGUAGE FlexibleInstances #-}
5 {-# LANGUAGE MultiParamTypeClasses #-}
6 {-# LANGUAGE OverloadedStrings #-}
7 {-# LANGUAGE Rank2Types #-}
8 {-# LANGUAGE ScopedTypeVariables #-}
9 {-# LANGUAGE TypeFamilies #-}
10 {-# LANGUAGE TypeOperators #-}
11 -- | Expression for /lambda abstraction/s
12 -- in /Higher-Order Abstract Syntax/ (HOAS).
13 module Language.Symantic.Expr.Lambda where
14
15 import qualified Control.Applicative as Applicative
16 import qualified Data.Function as Fun
17 import Data.Monoid
18 import Data.Proxy (Proxy(..))
19 import Data.Type.Equality ((:~:)(Refl))
20 import Data.Text (Text)
21 import qualified Data.Text as Text
22 import Prelude hiding (const, id)
23
24 import Language.Symantic.Type
25 import Language.Symantic.Repr
26 import Language.Symantic.Expr.Root
27 import Language.Symantic.Expr.Error
28 import Language.Symantic.Expr.From
29 import Language.Symantic.Trans.Common
30
31 -- * Class 'Sym_Lambda'
32 -- | Symantic.
33 class Sym_Lambda repr where
34 -- | /Lambda application/.
35 ($$) :: repr ((->) arg res) -> repr arg -> repr res
36 default ($$) :: Trans t repr
37 => t repr ((->) arg res) -> t repr arg -> t repr res
38 ($$) f x = trans_lift (trans_apply f $$ trans_apply x)
39
40 -- | /Lambda abstraction/.
41 lam :: (repr arg -> repr res) -> repr ((->) arg res)
42 default lam :: Trans t repr
43 => (t repr arg -> t repr res) -> t repr ((->) arg res)
44 lam f = trans_lift $ lam $ trans_apply . f . trans_lift
45
46 -- | Convenient 'lam' and '$$' wrapper.
47 let_ :: repr var -> (repr var -> repr res) -> repr res
48 let_ x y = lam y $$ x
49
50 id :: repr a -> repr a
51 id a = (lam Fun.id) $$ a
52
53 const :: repr a -> repr b -> repr a
54 const a b = lam (lam . Fun.const) $$ a $$ b
55
56 -- | /Lambda composition/.
57 (#) :: repr (b -> c) -> repr (a -> b) -> repr a -> repr c
58 (#) f g a = f $$ (g $$ a)
59
60 flip :: repr (a -> b -> c) -> repr b -> repr a -> repr c
61 flip f b a = f $$ a $$ b
62
63 infixl 0 $$
64 infixr 9 #
65
66 instance Sym_Lambda Repr_Host where
67 ($$) = (Applicative.<*>)
68 lam f = Repr_Host (unRepr_Host . f . Repr_Host)
69 instance Sym_Lambda Repr_Text where
70 ($$) (Repr_Text a1) (Repr_Text a2) =
71 Repr_Text $ \p v ->
72 let p' = precedence_App in
73 paren p p' $ a1 p' v <> " " <> a2 p' v
74 lam f =
75 Repr_Text $ \p v ->
76 let p' = precedence_Lambda in
77 let x = "x" <> Text.pack (show v) in
78 paren p p' $
79 "\\" <> x <> " -> " <>
80 unRepr_Text (f (Repr_Text $ \_p _v -> x)) p' (succ v)
81 let_ e in_ =
82 Repr_Text $ \p v ->
83 let p' = precedence_Let in
84 let x = "x" <> Text.pack (show v) in
85 paren p p' $
86 "let" <> " " <> x <> " = " <> unRepr_Text e p (succ v) <> " in " <>
87 unRepr_Text (in_ (Repr_Text $ \_p _v -> x)) p (succ v)
88
89 precedence_Lambda :: Precedence
90 precedence_Lambda = Precedence 1
91 precedence_Let :: Precedence
92 precedence_Let = Precedence 3
93 precedence_Composition :: Precedence
94 precedence_Composition = Precedence 9
95
96 instance
97 ( Sym_Lambda r1
98 , Sym_Lambda r2
99 ) => Sym_Lambda (Dup r1 r2) where
100 ($$) (f1 `Dup` f2) (x1 `Dup` x2) = ($$) f1 x1 `Dup` ($$) f2 x2
101 lam f = dup1 (lam f) `Dup` dup2 (lam f)
102
103 -- * Type 'Expr_Lambda'
104 -- | Expression.
105 data Expr_Lambda (root:: *)
106 type instance Root_of_Expr (Expr_Lambda root) = root
107 type instance Type_of_Expr (Expr_Lambda root) = Type_Fun
108 type instance Sym_of_Expr (Expr_Lambda root) repr = Sym_Lambda repr
109 type instance Error_of_Expr ast (Expr_Lambda root) = Error_Expr_Lambda ast
110
111 -- | Parsing utility to check that the given type is a 'Type_Fun'
112 -- or raise 'Error_Expr_Type_mismatch'.
113 check_type_fun
114 :: forall ast ex root ty h ret.
115 ( root ~ Root_of_Expr ex
116 , ty ~ Type_Root_of_Expr ex
117 , Type0_Lift Type_Fun (Type_of_Expr root)
118 , Type0_Unlift Type_Fun (Type_of_Expr root)
119 , Error_Expr_Lift (Error_Expr (Error_of_Type ast ty) ty ast)
120 (Error_of_Expr ast root)
121 )
122 => Proxy ex -> ast -> ty h
123 -> (Type_Fun ty h -> Either (Error_of_Expr ast root) ret)
124 -> Either (Error_of_Expr ast root) ret
125 check_type_fun ex ast ty k =
126 case type0_unlift $ unType_Root ty of
127 Just ty_f -> k ty_f
128 Nothing -> Left $
129 error_expr ex $
130 Error_Expr_Type_mismatch ast
131 (Exists_Type0 (type_var0 SZero `type_fun` type_var0 (SSucc SZero)
132 :: ty ((->) Var0 Var0)))
133 (Exists_Type0 ty)
134
135 -- | Parse a /lambda variable/.
136 var_from
137 :: forall ast root hs ret.
138 ( Type0_From ast (Type_Root_of_Expr root)
139 , Error_Expr_Lift (Error_Expr_Lambda ast)
140 (Error_of_Expr ast root)
141 , Root_of_Expr root ~ root
142 ) => Text -> ExprFrom ast (Expr_Lambda root) hs ret
143 var_from name _ex ast = go
144 where
145 go :: forall ex hs'. (ex ~ (Expr_Lambda root))
146 => Lambda_Context (Lambda_Var (Type_Root_of_Expr ex)) hs'
147 -> ( forall h. Type_Root_of_Expr ex h
148 -> Forall_Repr_with_Context ex hs' h
149 -> Either (Error_of_Expr ast (Root_of_Expr ex)) ret )
150 -> Either (Error_of_Expr ast (Root_of_Expr ex)) ret
151 go c k' =
152 case c of
153 Lambda_Context_Empty -> Left $ error_expr_lift $
154 Error_Expr_Lambda_Var_unbound name ast
155 Lambda_Var n ty `Lambda_Context_Next` _ | n == name ->
156 k' ty $ Forall_Repr_with_Context $
157 \(repr `Lambda_Context_Next` _) -> repr
158 _ `Lambda_Context_Next` ctx' ->
159 go ctx' $ \ty (Forall_Repr_with_Context repr) ->
160 k' ty $ Forall_Repr_with_Context $
161 \(_ `Lambda_Context_Next` c') -> repr c'
162
163 -- | Parse 'app'.
164 app_from
165 :: forall ty ast root hs ret.
166 ( ty ~ Type_Root_of_Expr root
167 , Type0_From ast ty
168 , Type0_Eq ty
169 , Expr_From ast root
170 , Type0_Lift Type_Fun (Type_of_Expr root)
171 , Error_Expr_Lift (Error_Expr (Error_of_Type ast ty) ty ast)
172 (Error_of_Expr ast root)
173 , Type0_Unlift Type_Fun (Type_of_Expr root)
174 , Root_of_Expr root ~ root
175 ) => ast -> ast
176 -> ExprFrom ast (Expr_Lambda root) hs ret
177 app_from ast_lam ast_arg_actual ex ast ctx k =
178 expr_from (Proxy::Proxy root) ast_lam ctx $
179 \(ty_lam::ty h_lam) (Forall_Repr_with_Context l) ->
180 expr_from (Proxy::Proxy root) ast_arg_actual ctx $
181 \(ty_arg_actual::ty h_arg_actual)
182 (Forall_Repr_with_Context arg_actual) ->
183 case type0_unlift $ unType_Root ty_lam of
184 Nothing -> Left $
185 error_expr ex $
186 Error_Expr_Type_mismatch ast
187 (Exists_Type0 (type_var0 SZero `type_fun` type_var0 (SSucc SZero)
188 :: ty ((->) Var0 Var0)))
189 (Exists_Type0 ty_lam)
190 Just (Type2 Proxy ty_arg_expected ty_res
191 :: Type_Fun ty h_lam) ->
192 check_type0_eq ex ast
193 ty_arg_expected ty_arg_actual $ \Refl ->
194 k ty_res $ Forall_Repr_with_Context $
195 \c -> l c $$ arg_actual c
196
197 -- | Parse given /lambda abstraction/.
198 lam_from
199 :: forall ty ast root hs ret.
200 ( ty ~ Type_Root_of_Expr root
201 , root ~ Root_of_Expr root
202 , Type0_From ast ty
203 , Expr_From ast root
204 , Type0_Lift Type_Fun (Type_of_Expr root)
205 , Error_Expr_Lift (Error_Expr (Error_of_Type ast ty) ty ast)
206 (Error_of_Expr ast root)
207 ) => Text -> ast -> ast
208 -> ExprFrom ast (Expr_Lambda root) hs ret
209 lam_from name ast_ty_arg ast_body ex ast ctx k =
210 case type0_from (Proxy::Proxy ty)
211 ast_ty_arg (Right . Exists_Type0) of
212 Left err -> Left $ error_expr ex $ Error_Expr_Type err ast
213 Right (Exists_Type0 (ty_arg::ty h_arg)) ->
214 expr_from (Proxy::Proxy root) ast_body
215 (Lambda_Var name ty_arg `Lambda_Context_Next` ctx) $
216 \(ty_res::ty h_res) (Forall_Repr_with_Context res) ->
217 k (ty_arg `type_fun` ty_res
218 :: Root_of_Type ty ((->) h_arg h_res)) $
219 Forall_Repr_with_Context $
220 \c -> lam $
221 \arg -> res (arg `Lambda_Context_Next` c)
222
223 -- | Parse given /let/.
224 let_from
225 :: forall ty ast root hs ret.
226 ( ty ~ Type_Root_of_Expr root
227 , root ~ Root_of_Expr root
228 , Type0_From ast ty
229 , Expr_From ast root
230 , Error_Expr_Lift (Error_Expr (Error_of_Type ast ty) ty ast)
231 (Error_of_Expr ast root)
232 ) => Text -> ast -> ast
233 -> ExprFrom ast (Expr_Lambda root) hs ret
234 let_from name ast_var ast_body _ex _ast ctx k =
235 expr_from (Proxy::Proxy root) ast_var ctx $
236 \(ty_var::ty h_var) (Forall_Repr_with_Context var) ->
237 expr_from (Proxy::Proxy root) ast_body
238 (Lambda_Var name ty_var `Lambda_Context_Next` ctx) $
239 \(ty_res::ty h_res) (Forall_Repr_with_Context res) ->
240 k ty_res $ Forall_Repr_with_Context $
241 \c -> let_ (var c) $
242 \arg -> res (arg `Lambda_Context_Next` c)
243
244 -- * Type 'Error_Expr_Lambda'
245 data Error_Expr_Lambda ast
246 = Error_Expr_Lambda_Var_unbound Lambda_Var_Name ast
247 deriving (Eq, Show)