symantic-parser-0.1.0.20210201: src/Symantic/Parser/Haskell/Term.hs
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE TemplateHaskell #-}
-- | Haskell terms which are interesting
-- to pattern-match when optimizing.
module Symantic.Parser.Haskell.Term where
import Data.Bool (Bool(..))
import Data.Either (Either(..))
import Data.Eq (Eq)
import Data.Maybe (Maybe(..))
import Data.Functor.Identity (Identity(..))
import Prelude (undefined)
import Text.Show (Show(..))
import qualified Data.Eq as Eq
import qualified Data.Function as Fun
import qualified Language.Haskell.TH as TH
import qualified Language.Haskell.TH.Syntax as TH
import qualified Symantic.Univariant.Trans as Sym
-- * Class 'Termable'
-- | Single-out some Haskell terms in order to
class Termable repr where
-- | Application, aka. unabstract.
(.@) :: repr (a->b) -> repr a -> repr b
-- | Lambda term abstraction, in HOAS (Higher-Order Abstract Syntax) style.
lam :: (repr a -> repr b) -> repr (a->b)
-- | Like 'lam' but whose argument is used only once,
-- hence safe to beta-reduce (inline) without duplicating work.
lam1 :: (repr a -> repr b) -> repr (a->b)
-- Singled-out terms
bool :: Bool -> repr Bool
char :: (TH.Lift tok, Show tok) => tok -> repr tok
cons :: repr (a -> [a] -> [a])
nil :: repr [a]
eq :: Eq a => repr (a -> a -> Bool)
unit :: repr ()
left :: repr (l -> Either l r)
right :: repr (r -> Either l r)
nothing :: repr (Maybe a)
just :: repr (a -> Maybe a)
const :: repr (a -> b -> a)
flip :: repr ((a -> b -> c) -> b -> a -> c)
id :: repr (a->a)
(.) :: repr ((b->c) -> (a->b) -> a -> c)
($) :: repr ((a->b) -> a -> b)
default (.@) ::
Sym.Liftable2 repr => Termable (Sym.Output repr) =>
repr (a->b) -> repr a -> repr b
default lam ::
Sym.Liftable repr => Sym.Unliftable repr => Termable (Sym.Output repr) =>
(repr a -> repr b) -> repr (a->b)
default lam1 ::
Sym.Liftable repr => Sym.Unliftable repr => Termable (Sym.Output repr) =>
(repr a -> repr b) -> repr (a->b)
default bool ::
Sym.Liftable repr => Termable (Sym.Output repr) =>
Bool -> repr Bool
default char ::
Sym.Liftable repr => Termable (Sym.Output repr) =>
TH.Lift tok => Show tok =>
tok -> repr tok
default cons ::
Sym.Liftable repr => Termable (Sym.Output repr) =>
repr (a -> [a] -> [a])
default nil ::
Sym.Liftable repr => Termable (Sym.Output repr) =>
repr [a]
default eq ::
Sym.Liftable repr => Termable (Sym.Output repr) =>
Eq a => repr (a -> a -> Bool)
default unit ::
Sym.Liftable repr => Termable (Sym.Output repr) =>
repr ()
default left ::
Sym.Liftable repr => Termable (Sym.Output repr) =>
repr (l -> Either l r)
default right ::
Sym.Liftable repr => Termable (Sym.Output repr) =>
repr (r -> Either l r)
default nothing ::
Sym.Liftable repr => Termable (Sym.Output repr) =>
repr (Maybe a)
default just ::
Sym.Liftable repr => Termable (Sym.Output repr) =>
repr (a -> Maybe a)
default const ::
Sym.Liftable repr => Termable (Sym.Output repr) =>
repr (a -> b -> a)
default flip ::
Sym.Liftable repr => Termable (Sym.Output repr) =>
repr ((a -> b -> c) -> b -> a -> c)
default id ::
Sym.Liftable repr => Termable (Sym.Output repr) =>
repr (a->a)
default (.) ::
Sym.Liftable repr => Termable (Sym.Output repr) =>
repr ((b->c) -> (a->b) -> a -> c)
default ($) ::
Sym.Liftable repr => Termable (Sym.Output repr) =>
repr ((a->b) -> a -> b)
(.@) = Sym.lift2 (.@)
lam f = Sym.lift (lam (Sym.trans Fun.. f Fun.. Sym.trans))
lam1 f = Sym.lift (lam1 (Sym.trans Fun.. f Fun.. Sym.trans))
bool = Sym.lift Fun.. bool
char = Sym.lift Fun.. char
cons = Sym.lift cons
nil = Sym.lift nil
eq = Sym.lift eq
unit = Sym.lift unit
left = Sym.lift left
right = Sym.lift right
nothing = Sym.lift nothing
just = Sym.lift just
const = Sym.lift const
flip = Sym.lift flip
id = Sym.lift id
(.) = Sym.lift (.)
($) = Sym.lift ($)
infixr 0 $
infixr 9 .
infixl 9 .@
-- * Type 'ValueCode'
data ValueCode a = ValueCode
{ value :: a
, code :: TH.CodeQ a
}
instance Termable ValueCode where
f .@ x = ValueCode
{ value = runIdentity (Identity (value f) .@ (Identity (value x)))
, code = code f .@ code x
}
lam f = ValueCode
{ value = runIdentity (lam (Identity Fun.. value Fun.. f Fun.. (`ValueCode` undefined) Fun.. runIdentity))
, code = lam (code Fun.. f Fun.. ValueCode undefined)
}
lam1 = lam
bool b = ValueCode (runIdentity (bool b)) (bool b)
char c = ValueCode (runIdentity (char c)) (char c)
cons = ValueCode (runIdentity cons) cons
nil = ValueCode (runIdentity nil) nil
eq = ValueCode (runIdentity eq) eq
unit = ValueCode (runIdentity unit) unit
left = ValueCode (runIdentity left) left
right = ValueCode (runIdentity right) right
nothing = ValueCode (runIdentity nothing) nothing
just = ValueCode (runIdentity just) just
const = ValueCode (runIdentity const) const
flip = ValueCode (runIdentity flip) flip
id = ValueCode (runIdentity id) id
($) = ValueCode (runIdentity ($)) ($)
(.) = ValueCode (runIdentity (.)) (.)
instance Termable Identity where
f .@ x = Identity (runIdentity f (runIdentity x))
lam f = Identity (runIdentity Fun.. f Fun.. Identity)
lam1 = lam
bool = Identity
char = Identity
cons = Identity (:)
nil = Identity []
eq = Identity (Eq.==)
unit = Identity ()
left = Identity Left
right = Identity Right
nothing = Identity Nothing
just = Identity Just
const = Identity Fun.const
flip = Identity Fun.flip
id = Identity Fun.id
($) = Identity (Fun.$)
(.) = Identity (Fun..)
instance Termable TH.CodeQ where
(.@) f x = [|| $$f $$x ||]
lam f = [|| \x -> $$(f [||x||]) ||]
lam1 = lam
bool b = [|| b ||]
char c = [|| c ||]
cons = [|| (:) ||]
nil = [|| [] ||]
eq = [|| (Eq.==) ||]
unit = [|| () ||]
left = [|| Left ||]
right = [|| Right ||]
nothing = [|| Nothing ||]
just = [|| Just ||]
const = [|| Fun.const ||]
id = [|| \x -> x ||]
flip = [|| \f x y -> f y x ||]
($) = [|| (Fun.$) ||]
(.) = [|| (Fun..) ||]