module Numeric.Algebra.Free.Class
( FreeAlgebra(..)
, FreeCoalgebra(..)
) where
import Numeric.Semiring.Internal
import Data.Sequence
import Data.Monoid (mappend)
import Prelude ()
class Semiring r => FreeCoalgebra r c where
cojoin :: (c -> r) -> c -> c -> r
instance FreeAlgebra r m => FreeCoalgebra r (m -> r) where
cojoin k f g = k (f * g)
instance FreeCoalgebra () c where
cojoin _ _ _ = ()
instance (FreeAlgebra r b, FreeCoalgebra r c) => FreeCoalgebra (b -> r) c where
cojoin f c1 c2 b = cojoin (`f` b) c1 c2
instance (FreeCoalgebra r a, FreeCoalgebra r b) => FreeCoalgebra r (a, b) where
cojoin f (a1,b1) (a2,b2) = cojoin (\a -> cojoin (\b -> f (a,b)) b1 b2) a1 a2
instance (FreeCoalgebra r a, FreeCoalgebra r b, FreeCoalgebra r c) => FreeCoalgebra r (a, b, c) where
cojoin f (a1,b1,c1) (a2,b2,c2) = cojoin (\a -> cojoin (\b -> cojoin (\c -> f (a,b,c)) c1 c2) b1 b2) a1 a2
instance (FreeCoalgebra r a, FreeCoalgebra r b, FreeCoalgebra r c, FreeCoalgebra r d) => FreeCoalgebra r (a, b, c, d) where
cojoin f (a1,b1,c1,d1) (a2,b2,c2,d2) = cojoin (\a -> cojoin (\b -> cojoin (\c -> cojoin (\d -> f (a,b,c,d)) d1 d2) c1 c2) b1 b2) a1 a2
instance (FreeCoalgebra r a, FreeCoalgebra r b, FreeCoalgebra r c, FreeCoalgebra r d, FreeCoalgebra r e) => FreeCoalgebra r (a, b, c, d, e) where
cojoin f (a1,b1,c1,d1,e1) (a2,b2,c2,d2,e2) = cojoin (\a -> cojoin (\b -> cojoin (\c -> cojoin (\d -> cojoin (\e -> f (a,b,c,d,e)) e1 e2) d1 d2) c1 c2) b1 b2) a1 a2
instance Semiring r => FreeCoalgebra r [a] where
cojoin f as bs = f (mappend as bs)
instance Semiring r => FreeCoalgebra r (Seq a) where
cojoin f as bs = f (mappend as bs)