Search code examples
haskellcategory-theoryarrowscomonad

Arrowizing the Store comonad


I've been contributing for a past few weeks to a library that ports monads (mainly from mtl) to arrows.

Here's a quick example with the StateT monad from mtl:

newtype StateT s m a = StateT { runStateT :: s -> m (a, s) }
-- arrowization -->
newtype StateTA s a b c = StateTA { runStateTA :: a (b, s) (c, s) }

The "arrowizing" process wasn't really painful for most of the monads, but I can't figure out my arrow based on the Store comonad.

Every time I asked this question, people redirected me to the Cokleisli arrow, but will Cokleisli Store be equivalent to the arrow I'm looking for ?

The library being based on a mtl-style architecture (each arrow has a general class, like ArrowState, ArrowReader, etc...), I tried to figure out what will be the signatures of my functions in ArrowStore, but again, I can't.

I took a look at the arrows package which implements the same arrows as in the library I'm working on, but their CoState arrow (I heard CoState was another name for Store) defines no operations, so I guess the author also has troubles with this problem.

tl;dr:

  • Is Monad m => Kleisli m a b equivalent to the arrowized version m ?
  • Is it also true for comonads with the Cokleisli arrow ?
  • If so, how can I express the Store comonad as an arrow ?
  • If not, can we even "arrowize" comonads ?

Solution

  • Thanks to leftaroundabout's comment, I found the "arrowized" version of the Store comonad.

    My problem was that I couldn't find the "direct form" - as leftaroundabout mentions it - of my arrow. But, if what I want is Cokleisli Store then the answer is straightforward (not very formal notation but you get the idea):

    newtype CokleisliT a w b c = CokleisliT { runCokleisliT :: a (w b) c }
    newtype Store s a = Store (s -> a, s)
    
        Arrow a => CokleisliT a (Store s) b c
    <=> Arrow a => a (Store s b) c
    <=> Arrow a => a (s -> b, s) c
    

    From here, we can deduce the signatures of the ArrowStore class:

    class Arrow a => ArrowStore s a | a -> s where
        pos   :: a () s
        peek  :: a () b -> a s b
        peeks :: a () b -> a (s -> s) b
        seek  :: a (s, b) c -> a b c
        seeks :: a (s, b) c -> a (s -> s, b) c
    

    As for user's comment, apparently arrowizing a (co)monad is wrapping it in a (co)Kleisli arrow.

    Here's the library for the other arrows: https://github.com/felko/atl.