{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
module Control.Algebra.Free2
(
FreeAlgebra2 (..)
, Proof (..)
, AlgebraType0
, AlgebraType
, wrapFree2
, foldFree2
, unFoldNatFree2
, hoistFree2
, hoistFreeH2
, joinFree2
, bindFree2
, assocFree2
) where
import Control.Monad (join)
import Data.Kind (Type)
import Data.Algebra.Free (AlgebraType, AlgebraType0, Proof (..))
class FreeAlgebra2 (m :: (k -> k -> Type) -> k -> k -> Type) where
{-# MINIMAL liftFree2, foldNatFree2 #-}
liftFree2 :: AlgebraType0 m f
=> f a b
-> m f a b
foldNatFree2 :: forall (d :: k -> k -> Type)
(f :: k -> k -> Type) a b .
( AlgebraType m d
, AlgebraType0 m f
)
=> (forall x y. f x y -> d x y)
-> (m f a b -> d a b)
codom2 :: forall (f :: k -> k -> Type).
AlgebraType0 m f
=> Proof (AlgebraType m (m f)) (m f)
default codom2 :: forall a. AlgebraType m (m a)
=> Proof (AlgebraType m (m a)) (m a)
codom2 = Proof
forget2 :: forall (f :: k -> k -> Type).
AlgebraType m f
=> Proof (AlgebraType0 m f) (m f)
default forget2 :: forall a. AlgebraType0 m a
=> Proof (AlgebraType0 m a) (m a)
forget2 = Proof
wrapFree2 :: forall (m :: (Type -> Type -> Type) -> Type -> Type -> Type)
(f :: Type -> Type -> Type)
a b .
( AlgebraType0 m f
, FreeAlgebra2 m
, Monad (m f a)
)
=> f a (m f a b)
-> m f a b
wrapFree2 = join . liftFree2
{-# INLINABLE wrapFree2 #-}
foldFree2 :: forall (m :: (k -> k -> Type) -> k -> k -> Type)
(f :: k -> k -> Type)
a b .
( FreeAlgebra2 m
, AlgebraType m f
)
=> m f a b
-> f a b
foldFree2 = case forget2 :: Proof (AlgebraType0 m f) (m f) of
Proof -> foldNatFree2 id
{-# INLINABLE foldFree2 #-}
unFoldNatFree2
:: forall (m :: (k -> k -> Type) -> k -> k -> Type)
(f :: k -> k -> Type)
d a b.
( FreeAlgebra2 m
, AlgebraType0 m f
)
=> (forall x y. m f x y -> d x y)
-> f a b -> d a b
unFoldNatFree2 nat = nat . liftFree2
{-# INLINABLE unFoldNatFree2 #-}
hoistFree2 :: forall (m :: (k -> k -> Type) -> k -> k -> Type)
(f :: k -> k -> Type)
g a b .
( FreeAlgebra2 m
, AlgebraType0 m g
, AlgebraType0 m f
)
=> (forall x y. f x y -> g x y)
-> m f a b
-> m g a b
hoistFree2 nat = case codom2 :: Proof (AlgebraType m (m g)) (m g) of
Proof -> foldNatFree2 (liftFree2 . nat)
{-# INLINABLE [1] hoistFree2 #-}
{-# RULES
"hositFree2/foldNatFree2"
forall (nat :: forall (x :: k) (y :: k). g x y -> c x y)
(nat0 :: forall (x :: k) (y :: k). f x y -> g x y)
(f :: m f a b).
foldNatFree2 nat (hoistFree2 nat0 f) = foldNatFree2 (nat . nat0) f
#-}
hoistFreeH2 :: forall m n f a b .
( FreeAlgebra2 m
, FreeAlgebra2 n
, AlgebraType0 m f
, AlgebraType0 n f
, AlgebraType m (n f)
)
=> m f a b
-> n f a b
hoistFreeH2 = foldNatFree2 liftFree2
{-# INLINABLE [1] hoistFreeH2 #-}
{-# RULES
"hoistFreeH2/foldNatFree2" forall (nat :: forall (x :: k) (y :: k). f x y -> c x y)
(f :: AlgebraType m c => m f a b).
foldNatFree2 nat (hoistFreeH2 f) = foldNatFree2 nat f
#-}
joinFree2 :: forall (m :: (k -> k -> Type) -> k -> k -> Type)
(f :: k -> k -> Type)
a b .
( FreeAlgebra2 m
, AlgebraType0 m f
)
=> m (m f) a b
-> m f a b
joinFree2 = case codom2 :: Proof (AlgebraType m (m f)) (m f) of
Proof -> case forget2 :: Proof (AlgebraType0 m (m f)) (m (m f)) of
Proof -> foldFree2
{-# INLINABLE joinFree2 #-}
bindFree2 :: forall m f g a b .
( FreeAlgebra2 m
, AlgebraType0 m g
, AlgebraType0 m f
)
=> m f a b
-> (forall x y . f x y -> m g x y)
-> m g a b
bindFree2 mfa nat = case codom2 :: Proof (AlgebraType m (m g)) (m g) of
Proof -> foldNatFree2 nat mfa
{-# INLINABLE bindFree2 #-}
assocFree2 :: forall (m :: (Type -> Type -> Type) -> Type -> Type -> Type)
(f :: Type -> Type -> Type)
a b .
( FreeAlgebra2 m
, AlgebraType m f
, Functor (m (m f) a)
)
=> m f a (m f a b)
-> m (m f) a (f a b)
assocFree2 = case forget2 :: Proof (AlgebraType0 m f) (m f) of
Proof -> case codom2 :: Proof (AlgebraType m (m f)) (m f) of
Proof -> case forget2 :: Proof (AlgebraType0 m (m f)) (m (m f)) of
Proof -> case codom2 :: Proof (AlgebraType m (m (m f))) (m (m f)) of
Proof -> fmap foldFree2 . foldNatFree2 (hoistFree2 liftFree2 . liftFree2)
{-# INLINABLE assocFree2 #-}