{-# LANGUAGE DeriveFunctor, DeriveFoldable, DeriveTraversable #-} {-# OPTIONS_GHC -Wall #-} -- http://www.mail-archive.com/haskell@haskell.org/msg17244.html import Prelude hiding (id,(.),sum) import Control.Category import Control.Comonad import Data.Foldable hiding (sum) import Data.Traversable infixl 4 :> data History a = First a | History a :> a deriving (Functor, Foldable, Traversable, Show) runHistory :: (History a -> b) -> [a] -> [b] runHistory _ [] = [] runHistory f (a0:as0) = run (First a0) as0 where run az [] = [f az] run az (a:as) = f az : run (az :> a) as instance Comonad History where extend f w@First{} = First (f w) extend f w@(as :> _) = extend f as :> f w extract (First a) = a extract (_ :> a) = a instance ComonadApply History where First f <@> First a = First (f a) (_ :> f) <@> First a = First (f a) First f <@> (_ :> a) = First (f a) (fs :> f) <@> (as :> a) = (fs <@> as) :> f a fby :: a -> History a -> a a `fby` First _ = a _ `fby` (First b :> _) = b _ `fby` ((_ :> b) :> _) = b pos :: History a -> Int pos dx = wfix $ dx $> fby 0 . fmap (+1) sum :: Num a => History a -> a sum dx = extract dx + (0 `fby` extend sum dx) diff :: Num a => History a -> a diff dx = extract dx - fby 0 dx ini :: History a -> a ini dx = extract dx `fby` extend ini dx fibo :: Num b => History a -> b fibo d = wfix $ d $> fby 0 . extend (\dfibo -> extract dfibo + fby 1 dfibo) fibo' :: Num b => History a -> b fibo' d = fst $ wfix $ d $> fby (0, 1) . fmap (\(x, x') -> (x',x+x')) plus :: Num a => History a -> History a -> History a plus = liftW2 (+)