Description

The store comonad holds a constant value along with a modifiable accessor function, which maps the stored value to the focus.

This module defines the strict store (aka state-in-context/costate) comonad transformer.

stored value = (1, 5), accessor = fst, resulting focus = 1:

>>> :{
 let
storeTuple :: Store (Int, Int) Int
storeTuple = store fst (1, 5)
:}


>>> :{
 let
addToFocus :: Int -> Store (Int, Int) Int -> Int
addToFocus x wa = x + extract wa
:}

>>> :{
  let
added3 :: Store (Int, Int) Int
:}


The focus of added3 is now 1 + 3 = 4. However, this action changed only the accessor function and therefore the focus but not the stored value:

>>> pos added3
(1,5)

>>> extract added3
4


The strict store (state-in-context/costate) comonad transformer is subject to the laws:

x = seek (pos x) x
y = pos (seek y x)
seek y x = seek y (seek z x)

Thanks go to Russell O'Connor and Daniel Peebles for their help formulating and proving the laws for this comonad transformer.

Synopsis

type Store s = StoreT s Identity #

store :: (s -> a) -> s -> Store s a #

Create a Store using an accessor function and a stored value

runStore :: Store s a -> (s -> a, s) #

data StoreT s w a #

Constructors

 StoreT (w (s -> a)) s

Instances

 ComonadEnv e w => ComonadEnv e (StoreT t w) # Methodsask :: StoreT t w a -> e # Comonad w => ComonadStore s (StoreT s w) # Methodspos :: StoreT s w a -> s #peek :: s -> StoreT s w a -> a #peeks :: (s -> s) -> StoreT s w a -> a #seek :: s -> StoreT s w a -> StoreT s w a #seeks :: (s -> s) -> StoreT s w a -> StoreT s w a #experiment :: Functor f => (s -> f s) -> StoreT s w a -> f a # ComonadTraced m w => ComonadTraced m (StoreT s w) # Methodstrace :: m -> StoreT s w a -> a # # Methodscohoist :: (Comonad w, Comonad v) => (forall x. w x -> v x) -> StoreT s w a -> StoreT s v a # # Methodslower :: Comonad w => StoreT s w a -> w a # Functor w => Functor (StoreT s w) # Methodsfmap :: (a -> b) -> StoreT s w a -> StoreT s w b #(<$) :: a -> StoreT s w b -> StoreT s w a # (Applicative w, Monoid s) => Applicative (StoreT s w) # Methodspure :: a -> StoreT s w a #(<*>) :: StoreT s w (a -> b) -> StoreT s w a -> StoreT s w b #(*>) :: StoreT s w a -> StoreT s w b -> StoreT s w b #(<*) :: StoreT s w a -> StoreT s w b -> StoreT s w a # (ComonadApply w, Semigroup s) => ComonadApply (StoreT s w) # Methods(<@>) :: StoreT s w (a -> b) -> StoreT s w a -> StoreT s w b #(@>) :: StoreT s w a -> StoreT s w b -> StoreT s w b #(<@) :: StoreT s w a -> StoreT s w b -> StoreT s w a # Comonad w => Comonad (StoreT s w) # Methodsextract :: StoreT s w a -> a #duplicate :: StoreT s w a -> StoreT s w (StoreT s w a) #extend :: (StoreT s w a -> b) -> StoreT s w a -> StoreT s w b # runStoreT :: StoreT s w a -> (w (s -> a), s) # # Operations pos :: StoreT s w a -> s # Read the stored value >>> pos$ store fst (1,5)
(1,5)


seek :: s -> StoreT s w a -> StoreT s w a #

Set the stored value

>>> pos . seek (3,7) $store fst (1,5) (3,7)  Seek satisfies the law seek s = peek s . duplicate seeks :: (s -> s) -> StoreT s w a -> StoreT s w a # Modify the stored value >>> pos . seeks swap$ store fst (1,5)
(5,1)


Seeks satisfies the law

seeks f = peeks f . duplicate

peek :: Comonad w => s -> StoreT s w a -> a #

Peek at what the current focus would be for a different stored value

Peek satisfies the law

peek x . extend (peek y) = peek y

peeks :: Comonad w => (s -> s) -> StoreT s w a -> a #

Peek at what the current focus would be if the stored value was modified by some function

experiment :: (Comonad w, Functor f) => (s -> f s) -> StoreT s w a -> f a #

Applies a functor-valued function to the stored value, and then uses the new accessor to read the resulting focus.

>>> let f x = if x > 0 then Just (x^2) else Nothing
>>> experiment f $store (+1) 2 Just 5 >>> experiment f$ store (+1) (-2)
Nothing