packages feed

monad-ideals-0.1.0.0: test/CoidealExample.hs

{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE RankNTypes #-}
module CoidealExample where

import Control.Comonad
import Control.Comonad.Coideal
import Numeric.Natural (Natural)

-- * The example coideal

-- | Example coideal comonad
data A x = Src x x | Tgt x
  deriving (Show, Eq, Functor)

instance Comonad A where
  extract (Src x _) = x
  extract (Tgt x) = x

  duplicate ax@(Src _ x1) = Src ax (Tgt x1)
  duplicate ax@(Tgt _) = Tgt ax

-- | the only one nontrivial cokleisli arrow
advance :: A x -> x
advance ax = case ax of
  Src _ x' -> x'
  Tgt x -> x

-- Accumulating store
data Accum x = Accum Natural (Natural -> x)
  deriving Functor

instance Comonad Accum where
  extract (Accum _ f) = f 0
  duplicate (Accum n f) = Accum n $ \m1 -> Accum (n + m1) (\m2 -> f (m1 + m2))

data Accum' x = Accum' Natural (Natural -> x)
  deriving Functor

fromAccum' :: Coideal Accum' x -> Accum x
fromAccum' wx' = case runCoideal wx' of
  (x, Accum' n f) -> Accum n (\m -> if m == 0 then x else f (m - 1))

toAccum' :: Accum x -> Coideal Accum' x
toAccum' (Accum n f) = Coideal (f 0, Accum' n (\m -> f (m + 1)))

instance ComonadCoideal Accum' where
  coidealExtend k (Accum' n f) = Accum' n $ \m1 -> k (toAccum' $ Accum (n + 1 + m1) (\m2 -> f (m1 + m2)))

-- | Comonad morphism to A.
nextMultipleOf :: Natural -> Accum x -> A x
nextMultipleOf d (Accum n f) = case n `mod` d of
  0 -> Tgt (f 0)
  r -> Src (f 0) (f (d - r))

-- | ComonadIdeal morphism to A'
nextMultipleOf' :: Natural -> Accum' x -> A' x
nextMultipleOf' d (Accum' n f) = case n `mod` d of
  0 -> Tgt'
  r -> Src' (f (d - r - 1))

-- | The coideal part of A
data A' x = Src' x | Tgt'
  deriving (Show, Eq, Functor)

instance ComonadCoideal A' where
  coidealExtend f (Src' x) = Src' (f $ Coideal (x, Tgt'))
  coidealExtend _ Tgt' = Tgt'

fromA' :: Coideal A' x -> A x
fromA' ax' = case runCoideal ax' of
  (x, Src' x') -> Src x x'
  (x, Tgt') -> Tgt x

toA' :: A x -> Coideal A' x
toA' (Src x x') = Coideal (x, Src' x')
toA' (Tgt x) = Coideal (x, Tgt')