{-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE ViewPatterns #-} module Symantic.Typed.Data where import Data.Kind (Constraint, Type) import Type.Reflection (Typeable, (:~~:)(..), eqTypeRep, typeRep) import Data.Bool (Bool) import Data.Either (Either) import Data.Maybe (Maybe) import qualified Data.Eq as Eq import qualified Data.Maybe as Maybe import qualified Data.Function as Fun import Symantic.Typed.Lang import Symantic.Typed.Trans data SomeData repr a = forall able. ( Trans (Data able repr) repr , Typeable able ) => SomeData (Data able repr a) instance Trans (SomeData repr) repr where trans (SomeData x) = trans x type TypedRepr = Type -> Type -- TODO: neither data families nor data instances -- can have phantom roles with GHC-9's RoleAnnotations, -- hence 'Data.Coerce.coerce' cannot be used on them for now. -- https://gitlab.haskell.org/ghc/ghc/-/issues/8177 -- https://gitlab.haskell.org/ghc/ghc/-/wikis/roles#proposal-roles-for-type-families -- Would be useful for @Trans (Data able repr) (Data able repr')@ instances. data family Data (able :: TypedRepr -> Constraint) :: TypedRepr -> TypedRepr --instance Trans (Data able repr) (Data able repr) where -- trans = Fun.id -- | Convenient utility to pattern-match a 'SomeData'. pattern Data :: Typeable able => Data able repr a -> SomeData repr a pattern Data x <- (unSomeData -> Maybe.Just x) -- | @(unSomeData c :: 'Maybe' ('Data' able repr a))@ -- extract the data-constructor from the given 'SomeData' -- iif. it belongs to the @('Data' able repr a)@ data-instance. unSomeData :: forall able repr a. Typeable able => SomeData repr a -> Maybe (Data able repr a) unSomeData (SomeData (c::Data c repr a)) = case typeRep @able `eqTypeRep` typeRep @c of Maybe.Just HRefl -> Maybe.Just c Maybe.Nothing -> Maybe.Nothing -- Abstractable data instance Data Abstractable repr a where (:@) :: SomeData repr (a->b) -> SomeData repr a -> Data Abstractable repr b Lam :: (SomeData repr a -> SomeData repr b) -> Data Abstractable repr (a->b) Lam1 :: (SomeData repr a -> SomeData repr b) -> Data Abstractable repr (a->b) Var :: repr a -> Data Abstractable repr a -- FIXME: add constructors instance ( Abstractable repr --, Trans (SomeData repr) repr --, Trans repr (SomeData repr) ) => Trans (Data Abstractable repr) repr where trans = \case f :@ x -> trans f .@ trans x Lam f -> lam (\x -> trans (f (SomeData (Var x)))) Lam1 f -> lam1 (\x -> trans (f (SomeData (Var x)))) Var x -> var x instance ( Abstractable repr --, Trans (SomeData repr) repr --, Trans repr (SomeData repr) ) => Abstractable (SomeData repr) where f .@ x = SomeData (f :@ x) lam f = SomeData (Lam f) lam1 f = SomeData (Lam1 f) var = Fun.id ($) = lam1 (\f -> lam1 (\x -> f .@ x)) (.) = lam1 (\f -> lam1 (\g -> lam1 (\x -> f .@ (g .@ x)))) const = lam1 (\x -> lam1 (\_y -> x)) flip = lam1 (\f -> lam1 (\x -> lam1 (\y -> f .@ y .@ x))) id = lam1 (\x -> x) {- instance ( Abstractable repr ) => Abstractable (Data Abstractable repr) where var = Var Fun.. SomeData f .@ x = SomeData f :@ SomeData x lam f = Lam (SomeData Fun.. f Fun.. Var) lam1 f = Lam1 (SomeData Fun.. f Fun.. Var) ($) = lam1 (\f -> lam1 (\x -> f .@ x)) (.) = lam1 (\f -> lam1 (\g -> lam1 (\x -> f .@ (g .@ x)))) const = lam1 (\x -> lam1 (\_y -> x)) flip = lam1 (\f -> lam1 (\x -> lam1 (\y -> f .@ y .@ x))) id = lam1 (\x -> x) -} {- instance Bottomable repr => Morph (SomeData repr) (SomeData Unit) where morph (SomeData x) = morph x instance Bottomable repr => Morph (SomeData Unit) (SomeData repr) where morph (SomeData x) = morph x instance Abstractable Unit where (.@) _f _x = Unit lam _f = Unit lam1 _f = Unit ($) = Unit (.) = Unit const = Unit flip = Unit id = Unit instance Abstractable (Data Abstractable Unit) where f .@ x = SomeData f :@ SomeData x lam f = Lam (\(SomeData x) -> SomeData (f (trans x))) lam1 f = Lam1 (\(SomeData x) -> SomeData (f (trans x))) ($) = ($) (.) = (.) const = const flip = flip id = id -} -- Anythingable data instance Data Anythingable repr a where Anything :: repr a -> Data Anythingable repr a instance ( Anythingable repr ) => Trans (Data Anythingable repr) repr where trans = \case Anything x -> anything x instance Anythingable (SomeData repr) instance Anythingable (Data Anythingable repr) -- Bottomable class Bottomable repr where bottom :: repr a data instance Data Bottomable repr a where Bottom :: Data Bottomable repr a instance Bottomable repr => Trans (Data Bottomable repr) repr where trans Bottom{} = bottom -- Constantable data instance Data (Constantable c) repr a where Constant :: {-Typeable c =>-} c -> Data (Constantable c) repr c instance Constantable c repr => Trans (Data (Constantable c) repr) repr where trans = \case Constant x -> constant x instance ( Constantable c repr , Typeable c ) => Constantable c (SomeData repr) where constant c = SomeData (Constant c) instance {-Typeable c =>-} Constantable c (Data (Constantable c) repr) where constant = Constant -- Eitherable data instance Data Eitherable repr a where Left :: Data Eitherable repr (l -> Either l r) Right :: Data Eitherable repr (r -> Either l r) instance Eitherable repr => Trans (Data Eitherable repr) repr where trans = \case Left -> left Right -> right instance ( Eitherable repr ) => Eitherable (SomeData repr) where left = SomeData Left right = SomeData Right instance Eitherable (Data Eitherable repr) where left = Left right = Right -- Equalable data instance Data Equalable repr a where Equal :: Eq.Eq a => Data Equalable repr (a -> a -> Bool) instance Equalable repr => Trans (Data Equalable repr) repr where trans = \case Equal -> equal instance ( Equalable repr ) => Equalable (SomeData repr) where equal = SomeData Equal instance Equalable (Data Equalable repr) where equal = Equal -- IfThenElseable data instance Data IfThenElseable repr a where IfThenElse :: SomeData repr Bool -> SomeData repr a -> SomeData repr a -> Data IfThenElseable repr a instance IfThenElseable repr => Trans (Data IfThenElseable repr) repr where trans = \case IfThenElse test ok ko -> ifThenElse (trans test) (trans ok) (trans ko) instance ( IfThenElseable repr ) => IfThenElseable (SomeData repr) where ifThenElse test ok ko = SomeData (IfThenElse test ok ko) instance IfThenElseable repr => IfThenElseable (Data IfThenElseable repr) where ifThenElse test ok ko = IfThenElse (SomeData test) (SomeData ok) (SomeData ko) -- Listable data instance Data Listable repr a where Cons :: Data Listable repr (a -> [a] -> [a]) Nil :: Data Listable repr [a] infixr 4 `Cons` instance Listable repr => Trans (Data Listable repr) repr where trans = \case Cons -> cons Nil -> nil instance ( Listable repr ) => Listable (SomeData repr) where cons = SomeData Cons nil = SomeData Nil instance Listable (Data Listable repr) where cons = Cons nil = Nil -- Maybeable data instance Data Maybeable repr a where Nothing :: Data Maybeable repr (Maybe a) Just :: Data Maybeable repr (a -> Maybe a) instance Maybeable repr => Trans (Data Maybeable repr) repr where trans = \case Nothing -> nothing Just -> just instance ( Maybeable repr ) => Maybeable (SomeData repr) where nothing = SomeData Nothing just = SomeData Just instance Maybeable (Data Maybeable repr) where nothing = Nothing just = Just