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)
146 Functionable (SomeData sem)
148 ($) = lam (\f -> lam (\x -> f .@ x))
149 (.) = lam (\f -> lam (\g -> lam (\x -> f .@ (g .@ x))))
150 const = lam (\x -> lam (\_y -> x))
151 flip = lam (\f -> lam (\x -> lam (\y -> f .@ y .@ x)))
155 data instance Data Anythingable sem a where
156 Anything :: sem a -> Data Anythingable sem a
160 Derivable (Data Anythingable sem)
163 Anything x -> anything x
164 instance Anythingable (SomeData sem)
165 instance Anythingable (Data Anythingable sem)
168 data instance Data Bottomable sem a where
169 Bottom :: Data Bottomable sem a
170 instance Bottomable sem => Derivable (Data Bottomable sem) where
171 derive Bottom{} = bottom
174 data instance Data (Constantable c) sem a where
175 Constant {-Typeable c =>-} :: c -> Data (Constantable c) sem c
176 instance Constantable c sem => Derivable (Data (Constantable c) sem) where
178 Constant x -> constant x
183 Constantable c (SomeData sem)
185 constant c = SomeData (Constant c)
186 instance{-Typeable c =>-} Constantable c (Data (Constantable c) sem) where
190 data instance Data Eitherable sem a where
191 Either :: Data Eitherable sem ((l -> a) -> (r -> a) -> Either l r -> a)
192 Left :: Data Eitherable sem (l -> Either l r)
193 Right :: Data Eitherable sem (r -> Either l r)
194 instance Eitherable sem => Derivable (Data Eitherable sem) where
199 instance Eitherable sem => Eitherable (SomeData sem) where
200 either = SomeData Either
202 right = SomeData Right
203 instance Eitherable (Data Eitherable sem) where
209 data instance Data Equalable sem a where
210 Equal :: Eq.Eq a => Data Equalable sem (a -> a -> Bool)
211 instance Equalable sem => Derivable (Data Equalable sem) where
217 Equalable (SomeData sem)
219 equal = SomeData Equal
220 instance Equalable (Data Equalable sem) where
224 data instance Data Emptyable sem a where
225 Empty :: Data Emptyable sem a
226 instance Emptyable sem => Derivable (Data Emptyable sem) where
232 Emptyable (SomeData sem)
234 empty = SomeData Empty
235 instance Emptyable (Data Emptyable sem) where
239 data instance Data Semigroupable sem a where
240 Concat :: Semigroup a => Data Semigroupable sem (a -> a -> a)
242 instance Semigroupable sem => Derivable (Data Semigroupable sem) where
248 Semigroupable (SomeData sem)
250 concat = SomeData Concat
251 instance Semigroupable (Data Semigroupable sem) where
255 data instance Data IfThenElseable sem a where
260 Data IfThenElseable sem a
261 instance IfThenElseable sem => Derivable (Data IfThenElseable sem) where
263 IfThenElse test ok ko -> ifThenElse (derive test) (derive ok) (derive ko)
267 IfThenElseable (SomeData sem)
269 ifThenElse test ok ko = SomeData (IfThenElse test ok ko)
270 instance IfThenElseable sem => IfThenElseable (Data IfThenElseable sem) where
271 ifThenElse test ok ko = IfThenElse (SomeData test) (SomeData ok) (SomeData ko)
274 data instance Data Listable sem a where
275 Cons :: Data Listable sem (a -> [a] -> [a])
276 Nil :: Data Listable sem [a]
278 instance Listable sem => Derivable (Data Listable sem) where
285 Listable (SomeData sem)
289 instance Listable (Data Listable sem) where
294 data instance Data Maybeable sem a where
295 Nothing :: Data Maybeable sem (Maybe a)
296 Just :: Data Maybeable sem (a -> Maybe a)
297 instance Maybeable sem => Derivable (Data Maybeable sem) where
304 Maybeable (SomeData sem)
306 nothing = SomeData Nothing
308 instance Maybeable (Data Maybeable sem) where