1 {-# LANGUAGE ConstraintKinds #-}
3 {-# LANGUAGE DataKinds #-}
5 {-# LANGUAGE PatternSynonyms #-}
6 {-# LANGUAGE RankNTypes #-}
7 {-# LANGUAGE ViewPatterns #-}
9 -- | This module provides the intermediate semantic 'SomeData'
10 -- which interprets combinators as data constructors.
11 -- This enables to pattern-match on combinators
12 -- while keeping their extensibility.
13 module Symantic.Semantics.Data where
15 import Data.Bool (Bool)
16 import Data.Either (Either)
17 import Data.Eq qualified as Eq
18 import Data.Function qualified as Fun
19 import Data.Maybe (Maybe)
20 import Data.Maybe qualified as Maybe
21 import Data.Semigroup (Semigroup)
22 import Type.Reflection (Typeable, eqTypeRep, typeRep, (:~~:) (..))
24 import Symantic.Syntaxes.Classes
25 import Symantic.Syntaxes.Derive
30 ( Derivable (Data syn sem)
33 SomeData (Data syn sem a)
35 type instance Derived (SomeData sem) = sem
36 instance Derivable (SomeData sem) where
37 derive (SomeData x) = derive x
41 -- TODO: neither data families nor data instances
42 -- can have phantom roles with GHC-9's RoleAnnotations,
43 -- hence 'Data.Coerce.coerce' cannot be used on them for now.
44 -- https://gitlab.haskell.org/ghc/ghc/-/issues/8177
45 -- https://gitlab.haskell.org/ghc/ghc/-/wikis/roles#proposal-roles-for-type-families
46 data family Data (syn :: Syntax) :: Semantic -> Semantic
47 type instance Derived (Data syn sem) = sem
49 -- | Convenient utility to pattern-match a 'SomeData'.
50 pattern Data :: Typeable syn => Data syn sem a -> SomeData sem a
51 pattern Data x <- (unSomeData -> Maybe.Just x)
53 -- | @(unSomeData sd :: 'Maybe' ('Data' syn sem a))@
54 -- extract the data-constructor from the given 'SomeData' @(sd)@
55 -- iif. it belongs to the @('Data' syn sem a)@ data-instance.
60 Maybe (Data syn sem a)
61 unSomeData (SomeData (constr :: Data actualSyn sem a)) =
62 case typeRep @syn `eqTypeRep` typeRep @actualSyn of
63 Maybe.Just HRefl -> Maybe.Just constr
64 Maybe.Nothing -> Maybe.Nothing
67 data instance Data Abstractable sem a where
68 Lam :: (SomeData sem a -> SomeData sem b) -> Data Abstractable sem (a -> b)
69 instance (Abstractable sem, Varable sem) => Derivable (Data Abstractable sem) where
71 Lam f -> lam (\x -> derive (f (SomeData (Var x))))
72 instance (Abstractable sem, Varable sem) => Abstractable (SomeData sem) where
73 lam f = SomeData (Lam f)
76 data instance Data Abstractable1 sem a where
77 Lam1 :: (SomeData sem a -> SomeData sem b) -> Data Abstractable1 sem (a -> b)
78 instance (Abstractable1 sem, Varable sem) => Derivable (Data Abstractable1 sem) where
80 Lam1 f -> lam1 (\x -> derive (f (SomeData (Var x))))
81 instance (Abstractable1 sem, Varable sem) => Abstractable1 (SomeData sem) where
82 lam1 f = SomeData (Lam1 f)
85 data instance Data Varable sem a where
86 Var :: sem a -> Data Varable sem a
87 instance Varable sem => Derivable (Data Varable sem) where
90 instance Varable sem => Varable (SomeData sem) where
93 -- | Beta-reduce the left-most outer-most lambda abstraction (aka. normal-order reduction),
94 -- but to avoid duplication of work, only those manually marked
95 -- as using their variable at most once.
97 -- DOC: Demonstrating Lambda Calculus Reduction, Peter Sestoft, 2001,
98 -- https://www.itu.dk/people/sestoft/papers/sestoft-lamreduce.pdf
99 normalOrderReduction ::
105 IfThenElseable sem =>
108 normalOrderReduction = nor
110 nor :: SomeData sem b -> SomeData sem b
112 Data (Lam f) -> lam (nor Fun.. f)
113 Data (Lam1 f) -> lam1 (nor Fun.. f)
114 Data (x :@ y) -> case whnf x of
115 Data (Lam1 f) -> nor (f y)
116 x' -> nor x' .@ nor y
117 Data (IfThenElse test ok ko) ->
119 Data (Constant b :: Data (Constantable Bool) sem Bool) ->
120 if b then nor ok else nor ko
121 t -> ifThenElse (nor t) (nor ok) (nor ko)
124 whnf :: SomeData sem b -> SomeData sem b
126 Data (x :@ y) -> case whnf x of
127 Data (Lam1 f) -> whnf (f y)
132 data instance Data Instantiable sem a where
133 (:@) :: SomeData sem (a -> b) -> SomeData sem a -> Data Instantiable sem b
134 instance Instantiable sem => Derivable (Data Instantiable sem) where
136 f :@ x -> derive f .@ derive x
137 instance Instantiable sem => Instantiable (SomeData sem) where
138 f .@ x = SomeData (f :@ x)
141 data instance Data Unabstractable sem a where
142 Ap :: Data Unabstractable sem ((a -> b -> c) -> (a -> b) -> a -> c)
143 Const :: Data Unabstractable sem (a -> b -> a)
144 Id :: Data Unabstractable sem (a -> a)
145 (:.) :: Data Unabstractable sem ((b -> c) -> (a -> b) -> a -> c)
146 Flip :: Data Unabstractable sem ((a -> b -> c) -> b -> a -> c)
147 (:$) :: Data Unabstractable sem ((a -> b) -> a -> b)
148 instance Unabstractable sem => Derivable (Data Unabstractable sem) where
156 instance Unabstractable sem => Unabstractable (SomeData sem) where
158 const = SomeData Const
165 data instance Data Anythingable sem a where
166 Anything :: sem a -> Data Anythingable sem a
170 Derivable (Data Anythingable sem)
173 Anything x -> anything x
174 instance Anythingable (SomeData sem)
175 instance Anythingable (Data Anythingable sem)
178 data instance Data Bottomable sem a where
179 Bottom :: Data Bottomable sem a
180 instance Bottomable sem => Derivable (Data Bottomable sem) where
181 derive Bottom{} = bottom
184 data instance Data (Constantable c) sem a where
185 Constant {-Typeable c =>-} :: c -> Data (Constantable c) sem c
186 instance Constantable c sem => Derivable (Data (Constantable c) sem) where
188 Constant x -> constant x
193 Constantable c (SomeData sem)
195 constant c = SomeData (Constant c)
196 instance{-Typeable c =>-} Constantable c (Data (Constantable c) sem) where
200 data instance Data Eitherable sem a where
201 Either :: Data Eitherable sem ((l -> a) -> (r -> a) -> Either l r -> a)
202 Left :: Data Eitherable sem (l -> Either l r)
203 Right :: Data Eitherable sem (r -> Either l r)
204 instance Eitherable sem => Derivable (Data Eitherable sem) where
209 instance Eitherable sem => Eitherable (SomeData sem) where
210 either = SomeData Either
212 right = SomeData Right
213 instance Eitherable (Data Eitherable sem) where
219 data instance Data Equalable sem a where
220 Equal :: Eq.Eq a => Data Equalable sem (a -> a -> Bool)
221 instance Equalable sem => Derivable (Data Equalable sem) where
227 Equalable (SomeData sem)
229 equal = SomeData Equal
230 instance Equalable (Data Equalable sem) where
234 data instance Data Emptyable sem a where
235 Empty :: Data Emptyable sem a
236 instance Emptyable sem => Derivable (Data Emptyable sem) where
242 Emptyable (SomeData sem)
244 empty = SomeData Empty
245 instance Emptyable (Data Emptyable sem) where
249 data instance Data Semigroupable sem a where
250 Concat :: Semigroup a => Data Semigroupable sem (a -> a -> a)
252 instance Semigroupable sem => Derivable (Data Semigroupable sem) where
258 Semigroupable (SomeData sem)
260 concat = SomeData Concat
261 instance Semigroupable (Data Semigroupable sem) where
265 data instance Data IfThenElseable sem a where
270 Data IfThenElseable sem a
271 instance IfThenElseable sem => Derivable (Data IfThenElseable sem) where
273 IfThenElse test ok ko -> ifThenElse (derive test) (derive ok) (derive ko)
277 IfThenElseable (SomeData sem)
279 ifThenElse test ok ko = SomeData (IfThenElse test ok ko)
280 instance IfThenElseable sem => IfThenElseable (Data IfThenElseable sem) where
281 ifThenElse test ok ko = IfThenElse (SomeData test) (SomeData ok) (SomeData ko)
284 data instance Data Listable sem a where
285 Cons :: Data Listable sem (a -> [a] -> [a])
286 Nil :: Data Listable sem [a]
288 instance Listable sem => Derivable (Data Listable sem) where
295 Listable (SomeData sem)
299 instance Listable (Data Listable sem) where
304 data instance Data Maybeable sem a where
305 Nothing :: Data Maybeable sem (Maybe a)
306 Just :: Data Maybeable sem (a -> Maybe a)
307 instance Maybeable sem => Derivable (Data Maybeable sem) where
314 Maybeable (SomeData sem)
316 nothing = SomeData Nothing
318 instance Maybeable (Data Maybeable sem) where