comonads, io

Ashley Yakeley ashley@semantic.org
Tue, 31 Dec 2002 11:54:43 -0800


In article <oqznqrnz32.fsf@premise.demon.co.uk>,
 peter@premise.demon.co.uk (Peter G. Hancock) wrote:

> Frustratingly, I can't seem to grasp the intuition.  I'm aware that
> the state-monad s->(s,a) has a dual state-in-context 
> comonad (s,s->a). How does the side-effect manifest itself?  
> The (ineffective) hints the authors give revolve around the idea that
> side-effects "derive" from the context of a program.  Any other hints?
...
> I can't make the slightest sense of Kieburtz's OI co-monad, with
> commands like coGetChar :: OI Handle -> Char. 

I've been wondering this myself. I always think of an object of type "IO 
a" as "an imperative action that returns an a", but I have no similar 
understanding for "OI a". But I think OI programs have the same 
restrictions against unsafety as IO programs.

  class Comonad w where
    (=>>) :: w a -> (w a -> b) -> w b
    (.>>) :: w a -> b -> w b
    coeval :: w a -> a

  instance Comonad OI where etc.

The first thing I notice is that you can't create objects of type "OI 
a". I think your main program would be:

  main :: OI () -> ()

Equivalent to "unsafePerformIO" would be:

  unsafeOI :: OI ()

  unsafeMakeOI :: a -> OI a
  unsafeMakeOI a = unsafeOI .>> a

The other thing I notice is that functions of type "(Comonad w) => w a 
-> b" seem to be equivalent to functions of type "(Comonad w) => w () -> 
a -> b". For instance:

  coGetChar :: OI Handle -> Char
  coGetChar' :: OI () -> Handle -> Char

  coGetChar' oi h = coGetChar (oi .>> h)

  coGetChar oih = coGetChar' (oih .>> ()) (coeval oih)

You certainly can't pull anything like this with monads. This would 
suggest comonads don't need to by type-constructors at all. But I'm not 
sure if it's correct. Opinions?

-- 
Ashley Yakeley, Seattle WA