rings-0.1.2: src/Data/Semimodule/Algebra.hs
{-# LANGUAGE CPP #-}
{-# LANGUAGE Safe #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE RebindableSyntax #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE RankNTypes #-}
module Data.Semimodule.Algebra (
-- * Algebras
type FreeAlgebra
, Algebra(..)
, diag
, (.*.)
-- * Unital Algebras
, type FreeUnital
, Unital(..)
, unit
, unit'
-- * Coalgebras
, type FreeCoalgebra
, Coalgebra(..)
, codiag
, convolve
-- * Unital Coalgebras
, type FreeCounital
, Counital(..)
, counit
-- * Bialgebras
, type FreeBialgebra
, Bialgebra
-- * Tran
, Tran(..)
, Endo
, image
, (!#)
, (#!)
, (!#!)
, dimap'
, lmap'
, rmap'
, invmap
-- * Common linear transformations
, braid
, cobraid
, split
, cosplit
, projl
, projr
, compl
, compr
, complr
) where
import safe Control.Arrow
import safe Control.Applicative
import safe Control.Category (Category, (>>>), (<<<))
import safe Data.Bool
import safe Data.Functor.Rep
import safe Data.Semimodule
import safe Data.Semiring
import safe Data.Tuple (swap)
import safe Prelude (Ord, reverse)
import safe qualified Data.IntSet as IntSet
import safe qualified Data.Set as Set
import safe qualified Data.Sequence as Seq
import safe Data.Sequence hiding (reverse,index)
import safe Prelude hiding (Num(..), Fractional(..), negate, sum, product)
import safe qualified Control.Category as C
import safe Test.Logic hiding (join)
-------------------------------------------------------------------------------
-- Algebras
-------------------------------------------------------------------------------
-- | An algebra over a free module /f/.
--
-- Note that this is distinct from a < https://en.wikipedia.org/wiki/Free_algebra free algebra >.
--
type FreeAlgebra a f = (FreeSemimodule a f, Algebra a (Rep f))
-- | An algebra < https://en.wikipedia.org/wiki/Algebra_over_a_field#Generalization:_algebra_over_a_ring algebra > over a semiring.
--
-- Note that the algebra < https://en.wikipedia.org/wiki/Non-associative_algebra needn't be associative >.
--
class Semiring a => Algebra a b where
-- |
--
-- @
-- 'joined' = 'runTran' 'diagonal' '.' 'uncurry'
-- @
--
joined :: (b -> b -> a) -> b -> a
joined = runTran diagonal . uncurry
-- |
--
-- @
-- 'Data.Semimodule.Dual.rmap'' (\((c1,()),(c2,())) -> (c1,c2)) '$' ('C.id' '***' 'initial') 'C..' 'diagonal' = 'C.id'
-- 'Data.Semimodule.Dual.rmap'' (\(((),c1),((),c2)) -> (c1,c2)) '$' ('initial' '***' 'C.id') 'C..' 'diagonal' = 'C.id'
-- @
--
diagonal :: Tran a b (b,b)
diagonal = Tran $ joined . curry
-- | Obtain the diagonal of a tensor product as a vector.
--
-- When the coalgebra is trivial we have:
--
-- @ 'diag' f = 'tabulate' $ 'joined' ('index' . 'index' ('getCompose' f)) @
--
-- >>> diag $ m22 1.0 2.0 3.0 4.0
-- V2 1.0 4.0
--
diag :: FreeAlgebra a f => (f**f) a -> f a
diag f = diagonal !# f
infixl 7 .*.
-- | Multiplication operator on an algebra over a free semimodule.
--
-- /Caution/ in general (.*.) needn't be commutative, nor associative.
--
(.*.) :: FreeAlgebra a f => f a -> f a -> f a
(.*.) x y = tabulate $ joined (\i j -> index x i * index y j)
-------------------------------------------------------------------------------
-- Unital algebras
-------------------------------------------------------------------------------
-- | A unital algebra over a free semimodule /f/.
--
type FreeUnital a f = (FreeAlgebra a f, Unital a (Rep f))
-- | A < https://en.wikipedia.org/wiki/Algebra_over_a_field#Unital_algebra unital algebra > over a semiring.
--
class Algebra a b => Unital a b where
-- |
--
-- @
-- 'unital' = 'runTran' 'initial' '.' 'const'
-- @
--
unital :: a -> b -> a
unital = runTran initial . const
initial :: Tran a b ()
initial = Tran $ \k -> unital $ k ()
-- | Insert an element into an algebra.
--
-- >>> V4 1 2 3 4 .*. unit two :: V4 Int
-- V4 2 4 6 8
--
unit :: FreeUnital a f => a -> f a
unit = tabulate . unital
-- | Unital element of a unital algebra over a free semimodule.
--
-- >>> unit one :: Complex Int
-- 1 :+ 0
--
unit' :: FreeUnital a f => f a
unit' = unit one
-------------------------------------------------------------------------------
-- Coalgebras
-------------------------------------------------------------------------------
-- | A coalgebra over a free semimodule /f/.
--
type FreeCoalgebra a f = (FreeSemimodule a f, Coalgebra a (Rep f))
-- | A coalgebra over a semiring.
--
class Semiring a => Coalgebra a c where
-- |
--
-- @
-- 'cojoined' = 'curry' '.' 'runTran' 'codiagonal'
-- @
--
cojoined :: (c -> a) -> c -> c -> a
cojoined = curry . runTran codiagonal
-- |
--
-- @
-- 'Data.Semimodule.Dual.lmap'' (\(c1,c2) -> ((c1,()),(c2,()))) '$' ('C.id' '***' 'coinitial') 'C..' 'codiagonal' = 'C.id'
-- 'Data.Semimodule.Dual.lmap'' (\(c1,c2) -> (((),c1),((),c2))) '$' ('coinitial' '***' 'C.id') 'C..' 'codiagonal' = 'C.id'
-- @
--
codiagonal :: Tran a (c,c) c
codiagonal = Tran $ uncurry . cojoined
{-
prop_cojoined (~~) f = (codiagonal !# f) ~~ (Compose . tabulate $ \i -> tabulate $ \j -> cojoined (index f) i j)
-- trivial coalgebra
prop_codiagonal' (~~) f = (codiagonal !# f) ~~ (Compose $ flip imapRep f $ \i x -> flip imapRep f $ \j _ -> bool zero x $ (i == j))
-- trivial coalgebra
prop_codiagonal (~~) f = (codiagonal !# f) ~~ (flip bindRep id . getCompose $ f)
prop_diagonal (~~) f = (diagonal !# f) ~~ (tabulate $ joined (index . index (getCompose f)))
-}
-- | Obtain a tensor from a vector.
--
-- When the coalgebra is trivial we have:
--
-- @ 'codiag' = 'flip' 'bindRep' 'id' '.' 'getCompose' @
--
codiag :: FreeCoalgebra a f => f a -> (f**f) a
codiag f = codiagonal !# f
{-
λ> foo = convolve (tran $ m22 1 0 0 1) (tran $ m22 1 0 0 1)
λ> foo !# V2 1 2 :: V2 Int
V2 1 2
λ> foo = convolve (tran $ m22 1 0 0 1) (tran $ m22 1 1 1 1)
λ> foo !# V2 1 2 :: V2 Int
V2 1 2
λ> foo = convolve (tran $ m22 1 1 1 1) (tran $ m22 1 1 1 1)
λ> foo !# V2 1 2 :: V2 Int
V2 3 3
-}
-- | Convolution with an associative algebra and coassociative coalgebra
--
--
convolve :: Algebra a b => Coalgebra a c => Tran a b c -> Tran a b c -> Tran a b c
convolve f g = codiagonal <<< (f *** g) <<< diagonal
-------------------------------------------------------------------------------
-- Counital Coalgebras
-------------------------------------------------------------------------------
-- | A counital coalgebra over a free semimodule /f/.
--
type FreeCounital a f = (FreeCoalgebra a f, Counital a (Rep f))
-- | A counital coalgebra over a semiring.
--
class Coalgebra a c => Counital a c where
-- @
-- 'counital' = 'flip' ('runTran' 'coinitial') '()'
-- @
--
counital :: (c -> a) -> a
counital = flip (runTran coinitial) ()
coinitial :: Tran a () c
coinitial = Tran $ const . counital
-- | Obtain an element from a coalgebra over a free semimodule.
--
counit :: FreeCounital a f => f a -> a
counit = counital . index
-------------------------------------------------------------------------------
-- Bialgebras
-------------------------------------------------------------------------------
-- | A bialgebra over a free semimodule /f/.
--
type FreeBialgebra a f = (FreeAlgebra a f, FreeCoalgebra a f, Bialgebra a (Rep f))
-- | A < https://en.wikipedia.org/wiki/Bialgebra bialgebra > over a semiring.
--
class (Unital a b, Counital a b) => Bialgebra a b
-------------------------------------------------------------------------------
-- General linear transformations
-------------------------------------------------------------------------------
-- | A linear transformation between free semimodules indexed with bases /b/ and /c/.
--
-- @
-- f '!#' x '+' y = (f '!#' x) + (f '!#' y)
-- f '!#' (r '.*' x) = r '.*' (f '!#' x)
-- @
--
-- /Caution/: You must ensure these laws hold when using the default constructor.
--
-- Prefer 'image' or 'Data.Semimodule.Operator.tran' where appropriate.
--
newtype Tran a b c = Tran { runTran :: (c -> a) -> b -> a }
-- | An endomorphism over a free semimodule.
--
-- >>> one + two !# V2 1 2 :: V2 Double
-- V2 3.0 6.0
--
type Endo a b = Tran a b b
-- | Create a 'Tran' from a linear combination of basis vectors.
--
-- >>> image (e2 [(2, E31),(3, E32)] [(1, E33)]) !# V3 1 1 1 :: V2 Int
-- V2 5 1
--
image :: Semiring a => (b -> [(a, c)]) -> Tran a b c
image f = Tran $ \k b -> sum [ a * k c | (a, c) <- f b ]
infixr 2 !#
-- | Apply a transformation to a vector.
--
(!#) :: Free f => Free g => Tran a (Rep f) (Rep g) -> g a -> f a
(!#) t = tabulate . runTran t . index
infixl 2 #!
-- | Apply a transformation to a vector.
--
(#!) :: Free f => Free g => g a -> Tran a (Rep f) (Rep g) -> f a
(#!) = flip (!#)
infix 2 !#!
-- | Compose two transformations.
--
(!#!) :: Tran a c d -> Tran a b c -> Tran a b d
(!#!) = (C..)
-- | 'Tran' is a profunctor in the category of semimodules.
--
-- /Caution/: Arbitrary mapping functions may violate linearity.
--
-- >>> dimap' id (e3 True True False) (arr id) !# 4 :+ 5 :: V3 Int
-- V3 5 5 4
--
dimap' :: (b1 -> b2) -> (c1 -> c2) -> Tran a b2 c1 -> Tran a b1 c2
dimap' l r f = arr r <<< f <<< arr l
lmap' :: (b1 -> b2) -> Tran a b2 c -> Tran a b1 c
lmap' l = dimap' l id
rmap' :: (c1 -> c2) -> Tran a b c1 -> Tran a b c2
rmap' = dimap' id
-- | 'Tran' is an invariant functor.
--
-- See also < http://comonad.com/reader/2008/rotten-bananas/ >.
--
invmap :: (a1 -> a2) -> (a2 -> a1) -> Tran a1 b c -> Tran a2 b c
invmap f g (Tran t) = Tran $ \x -> t (x >>> g) >>> f
-------------------------------------------------------------------------------
-- Common linear transformations
-------------------------------------------------------------------------------
-- | Swap components of a tensor product.
--
braid :: Tran a (b , c) (c , b)
braid = arr swap
{-# INLINE braid #-}
-- | Swap components of a direct sum.
--
cobraid :: Tran a (b + c) (c + b)
cobraid = arr eswap
{-# INLINE cobraid #-}
-- | TODO: Document
--
split :: (b -> (b1 , b2)) -> Tran a b1 c -> Tran a b2 c -> Tran a b c
split f x y = dimap' f fst $ x *** y
{-# INLINE split #-}
-- | TODO: Document
--
cosplit :: ((c1 + c2) -> c) -> Tran a b c1 -> Tran a b c2 -> Tran a b c
cosplit f x y = dimap' Left f $ x +++ y
{-# INLINE cosplit #-}
-- | Project onto the left-hand component of a direct sum.
--
projl :: Free f => Free g => (f++g) a -> f a
projl fg = arr Left !# fg
{-# INLINE projl #-}
-- | Project onto the right-hand component of a direct sum.
--
projr :: Free f => Free g => (f++g) a -> g a
projr fg = arr Right !# fg
{-# INLINE projr #-}
-- | Left (post) composition with a linear transformation.
--
compl :: Free f1 => Free f2 => Free g => Tran a (Rep f1) (Rep f2) -> (f2**g) a -> (f1**g) a
compl t fg = first t !# fg
-- | Right (pre) composition with a linear transformation.
--
compr :: Free f => Free g1 => Free g2 => Tran a (Rep g1) (Rep g2) -> (f**g2) a -> (f**g1) a
compr t fg = second t !# fg
-- | Left and right composition with a linear transformation.
--
-- @ 'complr' f g = 'compl' f '>>>' 'compr' g @
--
complr :: Free f1 => Free f2 => Free g1 => Free g2 => Tran a (Rep f1) (Rep f2) -> Tran a (Rep g1) (Rep g2) -> (f2**g2) a -> (f1**g1) a
complr t1 t2 fg = t1 *** t2 !# fg
-------------------------------------------------------------------------------
-- Instances
-------------------------------------------------------------------------------
instance Semiring a => Algebra a () where
joined f = f ()
instance Semiring a => Unital a () where
unital r () = r
instance (Algebra a b1, Algebra a b2) => Algebra a (b1, b2) where
joined f (a,b) = joined (\a1 a2 -> joined (\b1 b2 -> f (a1,b1) (a2,b2)) b) a
instance (Unital a b1, Unital a b2) => Unital a (b1, b2) where
unital r (a,b) = unital r a * unital r b
instance (Algebra a b1, Algebra a b2, Algebra a b3) => Algebra a (b1, b2, b3) where
joined f (a,b,c) = joined (\a1 a2 -> joined (\b1 b2 -> joined (\c1 c2 -> f (a1,b1,c1) (a2,b2,c2)) c) b) a
instance (Unital a b1, Unital a b2, Unital a b3) => Unital a (b1, b2, b3) where
unital r (a,b,c) = unital r a * unital r b * unital r c
-- | Tensor algebra on /b/.
--
-- >>> joined (<>) [1..3 :: Int]
-- [1,2,3,1,2,3,1,2,3,1,2,3]
--
-- >>> joined (\f g -> fold (f ++ g)) [1..3] :: Int
-- 24
--
instance Semiring a => Algebra a [b] where
joined f = go [] where
go ls rrs@(r:rs) = f (reverse ls) rrs + go (r:ls) rs
go ls [] = f (reverse ls) []
instance Semiring a => Unital a [b] where
unital a [] = a
unital _ _ = zero
instance Semiring a => Algebra a (Seq b) where
joined f = go Seq.empty where
go ls s = case viewl s of
EmptyL -> f ls s
r :< rs -> f ls s + go (ls |> r) rs
instance Semiring a => Unital a (Seq b) where
unital a b | Seq.null b = a
| otherwise = zero
instance (Semiring a, Ord b) => Algebra a (Set.Set b) where
joined f = go Set.empty where
go ls s = case Set.minView s of
Nothing -> f ls s
Just (r, rs) -> f ls s + go (Set.insert r ls) rs
instance (Semiring a, Ord b) => Unital a (Set.Set b) where
unital a b | Set.null b = a
| otherwise = zero
instance Semiring a => Algebra a IntSet.IntSet where
joined f = go IntSet.empty where
go ls s = case IntSet.minView s of
Nothing -> f ls s
Just (r, rs) -> f ls s + go (IntSet.insert r ls) rs
instance Semiring a => Unital a IntSet.IntSet where
unital a b | IntSet.null b = a
| otherwise = zero
---------------------------------------------------------------------
-- Coalgebra instances
---------------------------------------------------------------------
instance Semiring a => Coalgebra a () where
cojoined = const
instance Semiring a => Counital a () where
counital f = f ()
coinitial = Tran $ \f _ -> f ()
instance (Coalgebra a c1, Coalgebra a c2) => Coalgebra a (c1, c2) where
cojoined f (a1,b1) (a2,b2) = cojoined (\a -> cojoined (\b -> f (a,b)) b1 b2) a1 a2
instance (Counital a c1, Counital a c2) => Counital a (c1, c2) where
counital k = counital $ \a -> counital $ \b -> k (a,b)
instance (Coalgebra a c1, Coalgebra a c2, Coalgebra a c3) => Coalgebra a (c1, c2, c3) where
cojoined f (a1,b1,c1) (a2,b2,c2) = cojoined (\a -> cojoined (\b -> cojoined (\c -> f (a,b,c)) c1 c2) b1 b2) a1 a2
instance (Counital a c1, Counital a c2, Counital a c3) => Counital a (c1, c2, c3) where
counital k = counital $ \a -> counital $ \b -> counital $ \c -> k (a,b,c)
instance Algebra a b => Coalgebra a (b -> a) where
cojoined k f g = k (f * g)
instance Unital a b => Counital a (b -> a) where
coinitial = Tran $ \f _ -> f one
-- | The tensor coalgebra on /c/.
--
instance Semiring a => Coalgebra a [c] where
cojoined f as bs = f (mappend as bs)
instance Semiring a => Counital a [c] where
coinitial = Tran $ \f _ -> f []
instance Semiring a => Coalgebra a (Seq c) where
cojoined f as bs = f (mappend as bs)
instance Semiring a => Counital a (Seq c) where
coinitial = Tran $ \f _ -> f Seq.empty
-- | The free commutative band coalgebra
instance (Semiring a, Ord c) => Coalgebra a (Set.Set c) where
cojoined f as bs = f (Set.union as bs)
instance (Semiring a, Ord c) => Counital a (Set.Set c) where
coinitial = Tran $ \f _ -> f Set.empty
-- | The free commutative band coalgebra over Int
instance Semiring a => Coalgebra a IntSet.IntSet where
cojoined f as bs = f (IntSet.union as bs)
instance Semiring a => Counital a IntSet.IntSet where
coinitial = Tran $ \f _ -> f IntSet.empty
{-
-- | The free commutative coalgebra over a set and a given semigroup
instance (Semiring r, Ord a, Additive b) => Coalgebra r (Map a b) where
cojoined f as bs = f (Map.unionWith (+) as bs)
counital k = k (Map.empty)
-- | The free commutative coalgebra over a set and Int
instance (Semiring r, Additive b) => Coalgebra r (IntMap b) where
cojoined f as bs = f (IntMap.unionWith (+) as bs)
counital k = k (IntMap.empty)
-}
---------------------------------------------------------------------
-- Bialgebra instances
---------------------------------------------------------------------
instance Semiring a => Bialgebra a () where
instance (Bialgebra a b1, Bialgebra a b2) => Bialgebra a (b1, b2) where
instance (Bialgebra a b1, Bialgebra a b2, Bialgebra a b3) => Bialgebra a (b1, b2, b3) where
instance Semiring a => Bialgebra a [b]
instance Semiring a => Bialgebra a (Seq b)
-------------------------------------------------------------------------------
-- Tran instances
-------------------------------------------------------------------------------
addTran :: (Additive-Semigroup) a => Tran a b c -> Tran a b c -> Tran a b c
addTran (Tran f) (Tran g) = Tran $ f + g
subTran :: (Additive-Group) a => Tran a b c -> Tran a b c -> Tran a b c
subTran (Tran f) (Tran g) = Tran $ \h -> f h - g h
-- mulTran :: (Multiplicative-Semigroup) a => Tran a b c -> Tran a b c -> Tran a b c
-- mulTran (Tran f) (Tran g) = Tran $ \h -> f h * g h
instance Functor (Tran a b) where
fmap f m = Tran $ \k -> m !# k . f
instance Applicative (Tran a b) where
pure a = Tran $ \k _ -> k a
mf <*> ma = Tran $ \k b -> (mf !# \f -> (ma !# k . f) b) b
instance Monad (Tran a b) where
return a = Tran $ \k _ -> k a
m >>= f = Tran $ \k b -> (m !# \a -> (f a !# k) b) b
instance Category (Tran a) where
id = Tran id
Tran f . Tran g = Tran $ g . f
instance Arrow (Tran a) where
arr f = Tran (. f)
first m = Tran $ \k (a,c) -> (m !# \b -> k (b,c)) a
second m = Tran $ \k (c,a) -> (m !# \b -> k (c,b)) a
m *** n = Tran $ \k (a,c) -> (m !# \b -> (n !# \d -> k (b,d)) c) a
m &&& n = Tran $ \k a -> (m !# \b -> (n !# \c -> k (b,c)) a) a
instance ArrowChoice (Tran a) where
left m = Tran $ \k -> either (m !# k . Left) (k . Right)
right m = Tran $ \k -> either (k . Left) (m !# k . Right)
m +++ n = Tran $ \k -> either (m !# k . Left) (n !# k . Right)
m ||| n = Tran $ \k -> either (m !# k) (n !# k)
instance ArrowApply (Tran a) where
app = Tran $ \k (f,a) -> (f !# k) a
instance (Additive-Monoid) a => ArrowZero (Tran a) where
zeroArrow = Tran zero
instance (Additive-Monoid) a => ArrowPlus (Tran a) where
(<+>) = addTran
instance (Additive-Semigroup) a => Semigroup (Additive (Tran a b c)) where
(<>) = liftA2 addTran
instance (Additive-Monoid) a => Monoid (Additive (Tran a b c)) where
mempty = pure . Tran $ const zero
instance Coalgebra a c => Semigroup (Multiplicative (Tran a b c)) where
(<>) = liftR2 $ \ f g -> Tran $ \k b -> (f !# \a -> (g !# cojoined k a) b) b
instance Counital a c => Monoid (Multiplicative (Tran a b c)) where
mempty = pure . Tran $ \k _ -> counital k
instance Coalgebra a c => Presemiring (Tran a b c)
instance Counital a c => Semiring (Tran a b c)
instance Counital a m => LeftSemimodule (Tran a b m) (Tran a b m) where
lscale = (*)
instance LeftSemimodule r s => LeftSemimodule r (Tran s b m) where
lscale s (Tran m) = Tran $ \k b -> s *. m k b
instance Counital a m => RightSemimodule (Tran a b m) (Tran a b m) where
rscale = (*)
instance RightSemimodule r s => RightSemimodule r (Tran s b m) where
rscale s (Tran m) = Tran $ \k b -> m k b .* s
instance (Additive-Group) a => Magma (Additive (Tran a b c)) where
(<<) = liftR2 subTran
instance (Additive-Group) a => Quasigroup (Additive (Tran a b c)) where
instance (Additive-Group) a => Loop (Additive (Tran a b c)) where
instance (Additive-Group) a => Group (Additive (Tran a b c)) where
instance (Ring a, Counital a c) => Ring (Tran a b c)
{-
-- | An endomorphism of endomorphisms.
--
-- @ 'Cayley' a = (a -> a) -> (a -> a) @
--
type Cayley a = Tran a a a
-- | Lift a semiring element into a 'Cayley'.
--
-- @ 'runCayley' . 'cayley' = 'id' @
--
-- >>> runCayley . cayley $ 3.4 :: Double
-- 3.4
-- >>> runCayley . cayley $ m22 1 2 3 4 :: M22 Int
-- Compose (V2 (V2 1 2) (V2 3 4))
--
cayley :: Semiring a => a -> Cayley a
cayley a = Tran $ \k b -> a * k zero + b
-- | Extract a semiring element from a 'Cayley'.
--
-- >>> runCayley $ two * (one + (cayley 3.4)) :: Double
-- 8.8
-- >>> runCayley $ two * (one + (cayley $ m22 1 2 3 4)) :: M22 Int
-- Compose (V2 (V2 4 4) (V2 6 10))
--
runCayley :: Semiring a => Cayley a -> a
runCayley (Tran f) = f (one +) zero
-- ring homomorphism from a -> a^b
--embed :: Counital a c => (b -> a) -> Tran a b c
embed f = Tran $ \k b -> f b * k one
-- if the characteristic of s does not divide the order of a, then s[a] is semisimple
-- and if a has a length function, we can build a filtered algebra
-- | The < https://en.wikipedia.org/wiki/Augmentation_(algebra) augmentation > ring homomorphism from a^b -> a
--
augment :: Semiring a => Tran a b c -> b -> a
augment m = m !# const one
-}