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 Unabstractable (SomeData sem)
148 ap = lam (\abc -> lam (\ab -> lam (\a -> abc .@ a .@ (ab .@ a))))
149 const = lam (\x -> lam (\_y -> x))
151 (.) = lam (\f -> lam (\g -> lam (\x -> f .@ (g .@ x))))
152 flip = lam (\f -> lam (\x -> lam (\y -> f .@ y .@ x)))
153 ($) = lam (\f -> lam (\x -> f .@ x))
156 data instance Data Anythingable sem a where
157 Anything :: sem a -> Data Anythingable sem a
161 Derivable (Data Anythingable sem)
164 Anything x -> anything x
165 instance Anythingable (SomeData sem)
166 instance Anythingable (Data Anythingable sem)
169 data instance Data Bottomable sem a where
170 Bottom :: Data Bottomable sem a
171 instance Bottomable sem => Derivable (Data Bottomable sem) where
172 derive Bottom{} = bottom
175 data instance Data (Constantable c) sem a where
176 Constant {-Typeable c =>-} :: c -> Data (Constantable c) sem c
177 instance Constantable c sem => Derivable (Data (Constantable c) sem) where
179 Constant x -> constant x
184 Constantable c (SomeData sem)
186 constant c = SomeData (Constant c)
187 instance{-Typeable c =>-} Constantable c (Data (Constantable c) sem) where
191 data instance Data Eitherable sem a where
192 Either :: Data Eitherable sem ((l -> a) -> (r -> a) -> Either l r -> a)
193 Left :: Data Eitherable sem (l -> Either l r)
194 Right :: Data Eitherable sem (r -> Either l r)
195 instance Eitherable sem => Derivable (Data Eitherable sem) where
200 instance Eitherable sem => Eitherable (SomeData sem) where
201 either = SomeData Either
203 right = SomeData Right
204 instance Eitherable (Data Eitherable sem) where
210 data instance Data Equalable sem a where
211 Equal :: Eq.Eq a => Data Equalable sem (a -> a -> Bool)
212 instance Equalable sem => Derivable (Data Equalable sem) where
218 Equalable (SomeData sem)
220 equal = SomeData Equal
221 instance Equalable (Data Equalable sem) where
225 data instance Data Emptyable sem a where
226 Empty :: Data Emptyable sem a
227 instance Emptyable sem => Derivable (Data Emptyable sem) where
233 Emptyable (SomeData sem)
235 empty = SomeData Empty
236 instance Emptyable (Data Emptyable sem) where
240 data instance Data Semigroupable sem a where
241 Concat :: Semigroup a => Data Semigroupable sem (a -> a -> a)
243 instance Semigroupable sem => Derivable (Data Semigroupable sem) where
249 Semigroupable (SomeData sem)
251 concat = SomeData Concat
252 instance Semigroupable (Data Semigroupable sem) where
256 data instance Data IfThenElseable sem a where
261 Data IfThenElseable sem a
262 instance IfThenElseable sem => Derivable (Data IfThenElseable sem) where
264 IfThenElse test ok ko -> ifThenElse (derive test) (derive ok) (derive ko)
268 IfThenElseable (SomeData sem)
270 ifThenElse test ok ko = SomeData (IfThenElse test ok ko)
271 instance IfThenElseable sem => IfThenElseable (Data IfThenElseable sem) where
272 ifThenElse test ok ko = IfThenElse (SomeData test) (SomeData ok) (SomeData ko)
275 data instance Data Listable sem a where
276 Cons :: Data Listable sem (a -> [a] -> [a])
277 Nil :: Data Listable sem [a]
279 instance Listable sem => Derivable (Data Listable sem) where
286 Listable (SomeData sem)
290 instance Listable (Data Listable sem) where
295 data instance Data Maybeable sem a where
296 Nothing :: Data Maybeable sem (Maybe a)
297 Just :: Data Maybeable sem (a -> Maybe a)
298 instance Maybeable sem => Derivable (Data Maybeable sem) where
305 Maybeable (SomeData sem)
307 nothing = SomeData Nothing
309 instance Maybeable (Data Maybeable sem) where