167 lines
5.0 KiB
Haskell
167 lines
5.0 KiB
Haskell
{-# LANGUAGE UndecidableInstances #-}
|
|
module LambdaCalculus.Expression.Base
|
|
( Text, VoidF, absurd'
|
|
, Expr (..), Def, AppArgs, AbsArgs, LetArgs, XExpr
|
|
, ExprF (..), DefF (..), AppArgsF, LetArgsF, XExprF
|
|
, RecursivePhase, projectAppArgs, projectLetArgs, projectXExpr, projectDef
|
|
, embedAppArgs, embedLetArgs, embedXExpr, embedDef
|
|
) where
|
|
|
|
import Data.Functor.Foldable (Base, Recursive, Corecursive, project, embed)
|
|
import Data.Kind (Type)
|
|
import Data.Text (Text)
|
|
|
|
data Expr phase
|
|
-- | A variable: `x`.
|
|
= Var !Text
|
|
-- | Function application: `f x_0 ... x_n`.
|
|
| App !(Expr phase) !(AppArgs phase)
|
|
-- | Lambda abstraction: `λx_0 ... x_n. e`.
|
|
| Abs !(AbsArgs phase) !(Expr phase)
|
|
-- | Let expression: `let x_0 = v_0 ... ; x_n = v_n in e`.
|
|
| Let !(LetArgs phase) !(Expr phase)
|
|
-- | Additional phase-specific constructors.
|
|
| ExprX !(XExpr phase)
|
|
|
|
deriving instance
|
|
( Eq (AppArgs phase)
|
|
, Eq (AbsArgs phase)
|
|
, Eq (LetArgs phase)
|
|
, Eq (XExpr phase)
|
|
) => Eq (Expr phase)
|
|
|
|
deriving instance
|
|
( Show (AppArgs phase)
|
|
, Show (AbsArgs phase)
|
|
, Show (LetArgs phase)
|
|
, Show (XExpr phase)
|
|
) => Show (Expr phase)
|
|
|
|
type family AppArgs phase
|
|
type family AbsArgs phase
|
|
type family LetArgs phase
|
|
type family XExpr phase
|
|
|
|
-- | A definition, mapping a name to a value.
|
|
type Def phase = (Text, Expr phase)
|
|
|
|
---
|
|
--- Base functor boilerplate for recursion-schemes
|
|
---
|
|
|
|
data ExprF phase r
|
|
= VarF !Text
|
|
| AppF !r !(AppArgsF phase r)
|
|
| AbsF !(AbsArgs phase) r
|
|
| LetF !(LetArgsF phase r) r
|
|
| ExprXF !(XExprF phase r)
|
|
|
|
type instance Base (Expr phase) = ExprF phase
|
|
|
|
type family AppArgsF phase :: Type -> Type
|
|
type family LetArgsF phase :: Type -> Type
|
|
type family XExprF phase :: Type -> Type
|
|
|
|
data DefF r = DefF !Text !r
|
|
deriving (Eq, Functor, Show)
|
|
|
|
-- | An empty type with one extra type parameter.
|
|
data VoidF a
|
|
deriving (Eq, Functor, Foldable, Traversable, Show)
|
|
|
|
absurd' :: VoidF a -> b
|
|
absurd' x = case x of {}
|
|
|
|
instance
|
|
( Functor (AppArgsF phase)
|
|
, Functor (LetArgsF phase)
|
|
, Functor (XExprF phase)
|
|
) => Functor (ExprF phase) where
|
|
fmap f = \case
|
|
VarF n -> VarF n
|
|
AppF ef exs -> AppF (f ef) (fmap f exs)
|
|
AbsF ns e -> AbsF ns (f e)
|
|
LetF ds e -> LetF (fmap f ds) (f e)
|
|
ExprXF q -> ExprXF (fmap f q)
|
|
|
|
instance
|
|
( Foldable (AppArgsF phase)
|
|
, Foldable (LetArgsF phase)
|
|
, Foldable (XExprF phase)
|
|
) => Foldable (ExprF phase) where
|
|
foldMap f = \case
|
|
VarF _ -> mempty
|
|
AppF ef exs -> f ef <> foldMap f exs
|
|
AbsF _ e -> f e
|
|
LetF ds e -> foldMap f ds <> f e
|
|
ExprXF q -> foldMap f q
|
|
|
|
instance
|
|
( Traversable (AppArgsF phase)
|
|
, Traversable (LetArgsF phase)
|
|
, Traversable (XExprF phase)
|
|
) => Traversable (ExprF phase) where
|
|
traverse f = \case
|
|
VarF n -> pure $ VarF n
|
|
AppF ef exs -> AppF <$> f ef <*> traverse f exs
|
|
AbsF ns e -> AbsF ns <$> f e
|
|
LetF ds e -> LetF <$> traverse f ds <*> f e
|
|
ExprXF q -> ExprXF <$> traverse f q
|
|
|
|
class Functor (ExprF phase) => RecursivePhase phase where
|
|
projectAppArgs :: AppArgs phase -> AppArgsF phase (Expr phase)
|
|
projectLetArgs :: LetArgs phase -> LetArgsF phase (Expr phase)
|
|
projectXExpr :: XExpr phase -> XExprF phase (Expr phase)
|
|
|
|
embedAppArgs :: AppArgsF phase (Expr phase) -> AppArgs phase
|
|
embedLetArgs :: LetArgsF phase (Expr phase) -> LetArgs phase
|
|
embedXExpr :: XExprF phase (Expr phase) -> XExpr phase
|
|
|
|
default projectAppArgs :: AppArgs phase ~ AppArgsF phase (Expr phase)
|
|
=> AppArgs phase -> AppArgsF phase (Expr phase)
|
|
default projectLetArgs :: LetArgs phase ~ LetArgsF phase (Expr phase)
|
|
=> LetArgs phase -> LetArgsF phase (Expr phase)
|
|
default projectXExpr :: XExpr phase ~ XExprF phase (Expr phase)
|
|
=> XExpr phase -> XExprF phase (Expr phase)
|
|
|
|
default embedAppArgs :: AppArgsF phase (Expr phase) ~ AppArgs phase
|
|
=> AppArgsF phase (Expr phase) -> AppArgs phase
|
|
default embedLetArgs :: LetArgsF phase (Expr phase) ~ LetArgs phase
|
|
=> LetArgsF phase (Expr phase) -> LetArgs phase
|
|
default embedXExpr :: XExprF phase (Expr phase) ~ XExpr phase
|
|
=> XExprF phase (Expr phase) -> XExpr phase
|
|
|
|
projectAppArgs = id
|
|
projectLetArgs = id
|
|
projectXExpr = id
|
|
|
|
embedAppArgs = id
|
|
embedLetArgs = id
|
|
embedXExpr = id
|
|
|
|
projectDef :: Def phase -> DefF (Expr phase)
|
|
projectDef = uncurry DefF
|
|
|
|
embedDef :: DefF (Expr phase) -> Def phase
|
|
embedDef (DefF n e) = (n, e)
|
|
|
|
instance RecursivePhase phase => Recursive (Expr phase) where
|
|
project = \case
|
|
Var n -> VarF n
|
|
App ef exs -> AppF ef (projectAppArgs exs)
|
|
Abs ns e -> AbsF ns e
|
|
Let ds e -> LetF (projectLetArgs ds) e
|
|
ExprX q -> ExprXF (projectXExpr q)
|
|
|
|
instance RecursivePhase phase => Corecursive (Expr phase) where
|
|
embed = \case
|
|
VarF n -> Var n
|
|
AppF ef exs -> App ef (embedAppArgs exs)
|
|
AbsF ns e -> Abs ns e
|
|
LetF ds e -> Let (embedLetArgs ds) e
|
|
ExprXF q -> ExprX (embedXExpr q)
|
|
|
|
---
|
|
--- End base functor boilerplate.
|
|
---
|