{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeOperators #-}
module Language.Expression.Lambda where
import Data.Semigroup (Max (..))
import Data.Typeable ((:~:) (..), Typeable, eqT)
import Control.Lens
import Language.Expression
import Language.Expression.Scope
data LambdaOp s t a where
App :: t (a -> b) -> t a -> LambdaOp s t b
-- | Abstracts a scope where bound variables are in the @(':~:') a@ functor,
-- meaning they have the same type as @a@. Free variables ignore the argument
-- and have type @b@.
Abs :: s ((:~:) a) b -> LambdaOp s t (a -> b)
instance HDuofunctor LambdaOp where
hduomap = defaultHduomap
instance HDuotraversable LambdaOp where
hduotraverse f g = \case
App x y -> App <$> g x <*> g y
Abs x -> Abs <$> f pure x
instance HFunctor (LambdaOp s) where
hmap f = \case
App x y -> App (f x) (f y)
Abs x -> Abs x
instance (HTraversable s) => HTraversable (LambdaOp s) where
htraverse = hduotraverseSecond
instance HDuofoldableAt Identity LambdaOp where
hduofoldMapAt f = \case
App (Identity g) (Identity x) -> Identity (g x)
Abs y -> Identity (\x -> runIdentity (f (\Refl -> Identity x) y))
type LambdaExpr = SFree LambdaOp
-- var :: v a -> LambdaExpr
app :: LambdaExpr v (a -> b) -> LambdaExpr v a -> LambdaExpr v b
app f x = SWrap (App f x)
-- newtype Scope g h f a = Scope { unscope :: h (BV g (h f)) a }
lam' :: Scope ((:~:) a) LambdaExpr v b -> LambdaExpr v (a -> b)
lam' = SWrap . Abs . Scoped
data TVar k a where
TVar :: Typeable a => { tvarKey :: k } -> TVar k a
uniqueTVarKey :: (HTraversable h, Ord k, Bounded k, Enum k) => h (TVar k) a -> k
uniqueTVarKey x =
let Max highestUsed = hfoldMap (Max . tvarKey) x
in succ highestUsed
abstractTVar :: (HMonad h, Typeable a, Eq k) => k -> h (TVar k) b -> Scope ((:~:) a) h (TVar k) b
abstractTVar nm = abstract (\case TVar nm' | nm == nm' -> eqT
_ -> Nothing)
-- abstractTVar'
-- :: (HMonad h, HTraversable h, Typeable a, Ord k, Bounded k, Enum k, Typeable b)
-- => h (TVar k) b -> Scope ((:~:) a) h (TVar k) b
-- abstractTVar' x = abstractTVar (uniqueTVarKey x) x
-- -- | "Wow! This works?"
-- lam :: (Ord k, Bounded k, Enum k, Typeable a, Typeable b) => (LambdaExpr (TVar k) a -> LambdaExpr (TVar k) b) -> LambdaExpr (TVar k) (a -> b)
-- lam f =
-- let k = uniqueTVarKey
-- -- lam' $ abstractTVar' $ f _