{-# LANGUAGE CPP #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeApplications #-}
module Data.Algebra.Free
(
FreeAlgebra (..)
, Proof (..)
,
AlgebraType
, AlgebraType0
, unFoldMapFree
, foldFree
, natFree
, fmapFree
, joinFree
, bindFree
, cataFree
, foldrFree
, foldrFree'
, foldlFree
, foldlFree'
, Free (..)
, DNonEmpty (..)
)
where
import Prelude
#if __GLASGOW_HASKELL__ < 808
import Data.DList (DList)
#endif
import Data.DList as DList
import Data.Functor.Identity (Identity (..))
#if MIN_VERSION_data_fix(0,3,0)
import Data.Fix (Fix, foldFix)
#else
import Data.Fix (Fix, cata)
#endif
import Data.Group (Group (..))
import Data.Kind (Constraint, Type)
import Data.List.NonEmpty (NonEmpty (..))
import qualified Data.List.NonEmpty as NonEmpty
import Data.Monoid ( Endo (..)
#if __GLASGOW_HASKELL__ < 808
, Monoid (..)
#endif
, Dual (..))
#if __GLASGOW_HASKELL__ < 808
import Data.Semigroup ( Semigroup
, (<>)
)
#endif
import Data.Algebra.Pointed (Pointed (..))
type family AlgebraType (f :: k) (a :: l) :: Constraint
type family AlgebraType0 (f :: k) (a :: l) :: Constraint
data Proof (c :: Constraint) (a :: l) where
Proof :: c => Proof c a
class FreeAlgebra (m :: Type -> Type) where
{-# MINIMAL returnFree, foldMapFree #-}
returnFree :: a -> m a
foldMapFree
:: forall d a
. ( AlgebraType m d
, AlgebraType0 m a
)
=> (a -> d)
-> (m a -> d)
codom :: forall a. AlgebraType0 m a => Proof (AlgebraType m (m a)) (m a)
default codom :: forall a. AlgebraType m (m a)
=> Proof (AlgebraType m (m a)) (m a)
codom = Proof (AlgebraType m (m a)) (m a)
forall l (c :: Constraint) (a :: l). c => Proof c a
Proof
forget :: forall a. AlgebraType m a => Proof (AlgebraType0 m a) (m a)
default forget :: forall a. AlgebraType0 m a
=> Proof (AlgebraType0 m a) (m a)
forget = Proof (AlgebraType0 m a) (m a)
forall l (c :: Constraint) (a :: l). c => Proof c a
Proof
unFoldMapFree
:: FreeAlgebra m
=> (m a -> d)
-> (a -> d)
unFoldMapFree :: (m a -> d) -> a -> d
unFoldMapFree m a -> d
f = m a -> d
f (m a -> d) -> (a -> m a) -> a -> d
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> m a
forall (m :: * -> *) a. FreeAlgebra m => a -> m a
returnFree
{-# INLINABLE unFoldMapFree #-}
foldFree
:: forall m a .
( FreeAlgebra m
, AlgebraType m a
)
=> m a
-> a
foldFree :: m a -> a
foldFree m a
ma = case AlgebraType m a => Proof (AlgebraType0 m a) (m a)
forall (m :: * -> *) a.
(FreeAlgebra m, AlgebraType m a) =>
Proof (AlgebraType0 m a) (m a)
forget @m @a of
Proof (AlgebraType0 m a) (m a)
Proof -> (a -> a) -> m a -> a
forall (m :: * -> *) d a.
(FreeAlgebra m, AlgebraType m d, AlgebraType0 m a) =>
(a -> d) -> m a -> d
foldMapFree a -> a
forall a. a -> a
id m a
ma
{-# INLINABLE foldFree #-}
natFree :: forall m n a .
( FreeAlgebra m
, FreeAlgebra n
, AlgebraType0 m a
, AlgebraType m (n a)
)
=> m a
-> n a
natFree :: m a -> n a
natFree = (a -> n a) -> m a -> n a
forall (m :: * -> *) d a.
(FreeAlgebra m, AlgebraType m d, AlgebraType0 m a) =>
(a -> d) -> m a -> d
foldMapFree a -> n a
forall (m :: * -> *) a. FreeAlgebra m => a -> m a
returnFree
{-# INLINABLE natFree #-}
fmapFree :: forall m a b .
( FreeAlgebra m
, AlgebraType0 m a
, AlgebraType0 m b
)
=> (a -> b)
-> m a
-> m b
fmapFree :: (a -> b) -> m a -> m b
fmapFree a -> b
f m a
ma = case AlgebraType0 m b => Proof (AlgebraType m (m b)) (m b)
forall (m :: * -> *) a.
(FreeAlgebra m, AlgebraType0 m a) =>
Proof (AlgebraType m (m a)) (m a)
codom @m @b of
Proof (AlgebraType m (m b)) (m b)
Proof -> (a -> m b) -> m a -> m b
forall (m :: * -> *) d a.
(FreeAlgebra m, AlgebraType m d, AlgebraType0 m a) =>
(a -> d) -> m a -> d
foldMapFree (b -> m b
forall (m :: * -> *) a. FreeAlgebra m => a -> m a
returnFree (b -> m b) -> (a -> b) -> a -> m b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> b
f) m a
ma
{-# INLINABLE fmapFree #-}
joinFree :: forall m a .
( FreeAlgebra m
, AlgebraType0 m a
)
=> m (m a)
-> m a
joinFree :: m (m a) -> m a
joinFree m (m a)
mma = case AlgebraType0 m a => Proof (AlgebraType m (m a)) (m a)
forall (m :: * -> *) a.
(FreeAlgebra m, AlgebraType0 m a) =>
Proof (AlgebraType m (m a)) (m a)
codom @m @a of
Proof (AlgebraType m (m a)) (m a)
Proof -> m (m a) -> m a
forall (m :: * -> *) a.
(FreeAlgebra m, AlgebraType m a) =>
m a -> a
foldFree m (m a)
mma
{-# INLINABLE joinFree #-}
bindFree :: forall m a b .
( FreeAlgebra m
, AlgebraType0 m a
, AlgebraType0 m b
)
=> m a
-> (a -> m b)
-> m b
bindFree :: m a -> (a -> m b) -> m b
bindFree m a
ma a -> m b
f = case AlgebraType0 m b => Proof (AlgebraType m (m b)) (m b)
forall (m :: * -> *) a.
(FreeAlgebra m, AlgebraType0 m a) =>
Proof (AlgebraType m (m a)) (m a)
codom @m @b of
Proof (AlgebraType m (m b)) (m b)
Proof -> (a -> m b) -> m a -> m b
forall (m :: * -> *) d a.
(FreeAlgebra m, AlgebraType m d, AlgebraType0 m a) =>
(a -> d) -> m a -> d
foldMapFree a -> m b
f m a
ma
{-# INLINABLE bindFree #-}
cataFree :: ( FreeAlgebra m
, AlgebraType m a
, Functor m
)
=> Fix m
-> a
#if MIN_VERSION_data_fix(0,3,0)
cataFree :: Fix m -> a
cataFree = (m a -> a) -> Fix m -> a
forall (f :: * -> *) a. Functor f => (f a -> a) -> Fix f -> a
foldFix m a -> a
forall (m :: * -> *) a.
(FreeAlgebra m, AlgebraType m a) =>
m a -> a
foldFree
#else
cataFree = cata foldFree
#endif
foldrFree
:: forall m a b .
( FreeAlgebra m
, AlgebraType m (Endo b)
, AlgebraType0 m a
)
=> (a -> b -> b)
-> b
-> m a
-> b
foldrFree :: (a -> b -> b) -> b -> m a -> b
foldrFree a -> b -> b
f b
z m a
t = Endo b -> b -> b
forall a. Endo a -> a -> a
appEndo ((a -> Endo b) -> m a -> Endo b
forall (m :: * -> *) d a.
(FreeAlgebra m, AlgebraType m d, AlgebraType0 m a) =>
(a -> d) -> m a -> d
foldMapFree ((b -> b) -> Endo b
forall a. (a -> a) -> Endo a
Endo ((b -> b) -> Endo b) -> (a -> b -> b) -> a -> Endo b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> b -> b
f) m a
t) b
z
foldrFree'
:: forall m a b .
( FreeAlgebra m
, AlgebraType m (Dual (Endo (b -> b)))
, AlgebraType0 m a
)
=> (a -> b -> b)
-> m a
-> b
-> b
foldrFree' :: (a -> b -> b) -> m a -> b -> b
foldrFree' a -> b -> b
f m a
xs b
z0 = ((b -> b) -> a -> b -> b) -> (b -> b) -> m a -> b -> b
forall (m :: * -> *) a b.
(FreeAlgebra m, AlgebraType m (Dual (Endo b)), AlgebraType0 m a) =>
(b -> a -> b) -> b -> m a -> b
foldlFree (b -> b) -> a -> b -> b
f' b -> b
forall a. a -> a
id m a
xs b
z0
where
f' :: (b -> b) -> a -> b -> b
f' b -> b
k a
x b
z = b -> b
k (b -> b) -> b -> b
forall a b. (a -> b) -> a -> b
$! a -> b -> b
f a
x b
z
foldlFree
:: forall m a b .
( FreeAlgebra m
, AlgebraType m (Dual (Endo b))
, AlgebraType0 m a
)
=> (b -> a -> b)
-> b
-> m a
-> b
foldlFree :: (b -> a -> b) -> b -> m a -> b
foldlFree b -> a -> b
f b
z m a
t = Endo b -> b -> b
forall a. Endo a -> a -> a
appEndo (Dual (Endo b) -> Endo b
forall a. Dual a -> a
getDual ((a -> Dual (Endo b)) -> m a -> Dual (Endo b)
forall (m :: * -> *) d a.
(FreeAlgebra m, AlgebraType m d, AlgebraType0 m a) =>
(a -> d) -> m a -> d
foldMapFree (Endo b -> Dual (Endo b)
forall a. a -> Dual a
Dual (Endo b -> Dual (Endo b)) -> (a -> Endo b) -> a -> Dual (Endo b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (b -> b) -> Endo b
forall a. (a -> a) -> Endo a
Endo ((b -> b) -> Endo b) -> (a -> b -> b) -> a -> Endo b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (b -> a -> b) -> a -> b -> b
forall a b c. (a -> b -> c) -> b -> a -> c
flip b -> a -> b
f) m a
t)) b
z
foldlFree'
:: forall m a b .
( FreeAlgebra m
, AlgebraType m (Endo (b -> b))
, AlgebraType0 m a
)
=> (b -> a -> b)
-> b
-> m a
-> b
foldlFree' :: (b -> a -> b) -> b -> m a -> b
foldlFree' b -> a -> b
f b
z0 m a
xs = (a -> (b -> b) -> b -> b) -> (b -> b) -> m a -> b -> b
forall (m :: * -> *) a b.
(FreeAlgebra m, AlgebraType m (Endo b), AlgebraType0 m a) =>
(a -> b -> b) -> b -> m a -> b
foldrFree a -> (b -> b) -> b -> b
f' b -> b
forall a. a -> a
id m a
xs b
z0
where
f' :: a -> (b -> b) -> b -> b
f' a
x b -> b
k b
z = b -> b
k (b -> b) -> b -> b
forall a b. (a -> b) -> a -> b
$! b -> a -> b
f b
z a
x
type instance AlgebraType0 Identity a = ()
type instance AlgebraType Identity a = ()
instance FreeAlgebra Identity where
returnFree :: a -> Identity a
returnFree = a -> Identity a
forall a. a -> Identity a
Identity
foldMapFree :: (a -> d) -> Identity a -> d
foldMapFree a -> d
f = a -> d
f (a -> d) -> (Identity a -> a) -> Identity a -> d
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Identity a -> a
forall a. Identity a -> a
runIdentity
type instance AlgebraType0 NonEmpty a = ()
type instance AlgebraType NonEmpty m = Semigroup m
instance FreeAlgebra NonEmpty where
returnFree :: a -> NonEmpty a
returnFree a
a = a
a a -> [a] -> NonEmpty a
forall a. a -> [a] -> NonEmpty a
:| []
foldMapFree :: (a -> d) -> NonEmpty a -> d
foldMapFree a -> d
f (a
a :| []) = a -> d
f a
a
foldMapFree a -> d
f (a
a :| (a
b : [a]
bs)) = a -> d
f a
a d -> d -> d
forall a. Semigroup a => a -> a -> a
<> (a -> d) -> NonEmpty a -> d
forall (m :: * -> *) d a.
(FreeAlgebra m, AlgebraType m d, AlgebraType0 m a) =>
(a -> d) -> m a -> d
foldMapFree a -> d
f (a
b a -> [a] -> NonEmpty a
forall a. a -> [a] -> NonEmpty a
:| [a]
bs)
newtype DNonEmpty a = DNonEmpty ([a] -> NonEmpty a)
instance Semigroup (DNonEmpty a) where
DNonEmpty [a] -> NonEmpty a
f <> :: DNonEmpty a -> DNonEmpty a -> DNonEmpty a
<> DNonEmpty [a] -> NonEmpty a
g = ([a] -> NonEmpty a) -> DNonEmpty a
forall a. ([a] -> NonEmpty a) -> DNonEmpty a
DNonEmpty ([a] -> NonEmpty a
f ([a] -> NonEmpty a) -> ([a] -> [a]) -> [a] -> NonEmpty a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NonEmpty a -> [a]
forall a. NonEmpty a -> [a]
NonEmpty.toList (NonEmpty a -> [a]) -> ([a] -> NonEmpty a) -> [a] -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> NonEmpty a
g)
type instance AlgebraType0 DNonEmpty a = ()
type instance AlgebraType DNonEmpty m = Semigroup m
instance FreeAlgebra DNonEmpty where
returnFree :: a -> DNonEmpty a
returnFree a
a = ([a] -> NonEmpty a) -> DNonEmpty a
forall a. ([a] -> NonEmpty a) -> DNonEmpty a
DNonEmpty (a
a a -> [a] -> NonEmpty a
forall a. a -> [a] -> NonEmpty a
:|)
foldMapFree :: (a -> d) -> DNonEmpty a -> d
foldMapFree a -> d
f (DNonEmpty [a] -> NonEmpty a
g) = (a -> d) -> NonEmpty a -> d
forall (m :: * -> *) d a.
(FreeAlgebra m, AlgebraType m d, AlgebraType0 m a) =>
(a -> d) -> m a -> d
foldMapFree a -> d
f ([a] -> NonEmpty a
g [])
type instance AlgebraType0 [] a = ()
type instance AlgebraType [] m = Monoid m
instance FreeAlgebra [] where
returnFree :: a -> [a]
returnFree a
a = [a
a]
foldMapFree :: (a -> d) -> [a] -> d
foldMapFree = (a -> d) -> [a] -> d
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap
type instance AlgebraType0 Maybe a = ()
type instance AlgebraType Maybe m = Pointed m
instance FreeAlgebra Maybe where
returnFree :: a -> Maybe a
returnFree = a -> Maybe a
forall a. a -> Maybe a
Just
foldMapFree :: (a -> d) -> Maybe a -> d
foldMapFree a -> d
_ Maybe a
Nothing = d
forall p. Pointed p => p
point
foldMapFree a -> d
f (Just a
a) = a -> d
f a
a
newtype Free (c :: Type -> Constraint) a = Free {
Free c a -> forall r. c r => (a -> r) -> r
runFree :: forall r. c r => (a -> r) -> r
}
instance Semigroup (Free Semigroup a) where
Free forall r. Semigroup r => (a -> r) -> r
f <> :: Free Semigroup a -> Free Semigroup a -> Free Semigroup a
<> Free forall r. Semigroup r => (a -> r) -> r
g = (forall r. Semigroup r => (a -> r) -> r) -> Free Semigroup a
forall (c :: * -> Constraint) a.
(forall r. c r => (a -> r) -> r) -> Free c a
Free ((forall r. Semigroup r => (a -> r) -> r) -> Free Semigroup a)
-> (forall r. Semigroup r => (a -> r) -> r) -> Free Semigroup a
forall a b. (a -> b) -> a -> b
$ \a -> r
k -> (a -> r) -> r
forall r. Semigroup r => (a -> r) -> r
f a -> r
k r -> r -> r
forall a. Semigroup a => a -> a -> a
<> (a -> r) -> r
forall r. Semigroup r => (a -> r) -> r
g a -> r
k
type instance AlgebraType0 (Free Semigroup) a = ()
type instance AlgebraType (Free Semigroup) a = Semigroup a
instance FreeAlgebra (Free Semigroup) where
returnFree :: a -> Free Semigroup a
returnFree a
a = (forall r. Semigroup r => (a -> r) -> r) -> Free Semigroup a
forall (c :: * -> Constraint) a.
(forall r. c r => (a -> r) -> r) -> Free c a
Free ((forall r. Semigroup r => (a -> r) -> r) -> Free Semigroup a)
-> (forall r. Semigroup r => (a -> r) -> r) -> Free Semigroup a
forall a b. (a -> b) -> a -> b
$ \a -> r
k -> a -> r
k a
a
foldMapFree :: (a -> d) -> Free Semigroup a -> d
foldMapFree a -> d
f (Free forall r. Semigroup r => (a -> r) -> r
k) = (a -> d) -> d
forall r. Semigroup r => (a -> r) -> r
k a -> d
f
instance Semigroup (Free Monoid a) where
Free forall r. Monoid r => (a -> r) -> r
f <> :: Free Monoid a -> Free Monoid a -> Free Monoid a
<> Free forall r. Monoid r => (a -> r) -> r
g = (forall r. Monoid r => (a -> r) -> r) -> Free Monoid a
forall (c :: * -> Constraint) a.
(forall r. c r => (a -> r) -> r) -> Free c a
Free ((forall r. Monoid r => (a -> r) -> r) -> Free Monoid a)
-> (forall r. Monoid r => (a -> r) -> r) -> Free Monoid a
forall a b. (a -> b) -> a -> b
$ \a -> r
k -> (a -> r) -> r
forall r. Monoid r => (a -> r) -> r
f a -> r
k r -> r -> r
forall a. Monoid a => a -> a -> a
`mappend` (a -> r) -> r
forall r. Monoid r => (a -> r) -> r
g a -> r
k
instance Monoid (Free Monoid a) where
mempty :: Free Monoid a
mempty = (forall r. Monoid r => (a -> r) -> r) -> Free Monoid a
forall (c :: * -> Constraint) a.
(forall r. c r => (a -> r) -> r) -> Free c a
Free (r -> (a -> r) -> r
forall a b. a -> b -> a
const r
forall a. Monoid a => a
mempty)
#if __GLASGOW_HASKELL__ <= 802
mappend = (<>)
#endif
type instance AlgebraType0 (Free Monoid) a = ()
type instance AlgebraType (Free Monoid) a = Monoid a
instance FreeAlgebra (Free Monoid) where
returnFree :: a -> Free Monoid a
returnFree a
a = (forall r. Monoid r => (a -> r) -> r) -> Free Monoid a
forall (c :: * -> Constraint) a.
(forall r. c r => (a -> r) -> r) -> Free c a
Free ((forall r. Monoid r => (a -> r) -> r) -> Free Monoid a)
-> (forall r. Monoid r => (a -> r) -> r) -> Free Monoid a
forall a b. (a -> b) -> a -> b
$ \a -> r
k -> a -> r
k a
a
foldMapFree :: (a -> d) -> Free Monoid a -> d
foldMapFree a -> d
f (Free forall r. Monoid r => (a -> r) -> r
k) = (a -> d) -> d
forall r. Monoid r => (a -> r) -> r
k a -> d
f
type instance AlgebraType0 DList a = ()
type instance AlgebraType DList a = Monoid a
instance FreeAlgebra DList where
returnFree :: a -> DList a
returnFree = a -> DList a
forall a. a -> DList a
DList.singleton
foldMapFree :: (a -> d) -> DList a -> d
foldMapFree = (a -> d) -> DList a -> d
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap
instance Semigroup (Free Group a) where
Free forall r. Group r => (a -> r) -> r
f <> :: Free Group a -> Free Group a -> Free Group a
<> Free forall r. Group r => (a -> r) -> r
g = (forall r. Group r => (a -> r) -> r) -> Free Group a
forall (c :: * -> Constraint) a.
(forall r. c r => (a -> r) -> r) -> Free c a
Free ((forall r. Group r => (a -> r) -> r) -> Free Group a)
-> (forall r. Group r => (a -> r) -> r) -> Free Group a
forall a b. (a -> b) -> a -> b
$ \a -> r
k -> (a -> r) -> r
forall r. Group r => (a -> r) -> r
f a -> r
k r -> r -> r
forall a. Monoid a => a -> a -> a
`mappend` (a -> r) -> r
forall r. Group r => (a -> r) -> r
g a -> r
k
instance Monoid (Free Group a) where
mempty :: Free Group a
mempty = (forall r. Group r => (a -> r) -> r) -> Free Group a
forall (c :: * -> Constraint) a.
(forall r. c r => (a -> r) -> r) -> Free c a
Free (r -> (a -> r) -> r
forall a b. a -> b -> a
const r
forall a. Monoid a => a
mempty)
#if __GLASGOW_HASKELL__ <= 802
mappend = (<>)
#endif
instance Group (Free Group a) where
invert :: Free Group a -> Free Group a
invert (Free forall r. Group r => (a -> r) -> r
k) = (forall r. Group r => (a -> r) -> r) -> Free Group a
forall (c :: * -> Constraint) a.
(forall r. c r => (a -> r) -> r) -> Free c a
Free ((a -> r) -> r
forall r. Group r => (a -> r) -> r
k ((a -> r) -> r) -> ((a -> r) -> a -> r) -> (a -> r) -> r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> r) -> a -> r
forall m. Group m => m -> m
invert)
type instance AlgebraType0 (Free Group) a = ()
type instance AlgebraType (Free Group) a = Group a
instance FreeAlgebra (Free Group) where
returnFree :: a -> Free Group a
returnFree a
a = (forall r. Group r => (a -> r) -> r) -> Free Group a
forall (c :: * -> Constraint) a.
(forall r. c r => (a -> r) -> r) -> Free c a
Free ((forall r. Group r => (a -> r) -> r) -> Free Group a)
-> (forall r. Group r => (a -> r) -> r) -> Free Group a
forall a b. (a -> b) -> a -> b
$ \a -> r
k -> a -> r
k a
a
foldMapFree :: (a -> d) -> Free Group a -> d
foldMapFree a -> d
f (Free forall r. Group r => (a -> r) -> r
k) = (a -> d) -> d
forall r. Group r => (a -> r) -> r
k a -> d
f