
I came across an interesting paper "Codata and comonads in Haskell" by Richard Kieburtz, and some other work by Alberto Pardo on comonads. Kieburtz proposes an OI comonad, as an alternative to (or something alongside?) the IO monad. Just for reasons of symmetry, it's natural to wonder if they aren't as pervasive in functional programs as monads. 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? Are comonads especially appropriate for programming systems that react to changes in their environment? Is an object of OI type something like a program to react to events? I can't make the slightest sense of Kieburtz's OI co-monad, with commands like coGetChar :: OI Handle -> Char. Peter Hancock

In article
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

Hello, If I understand what you're saying, it seems that an intuitive view of OI would be : passing a token allowing to do IO operations. We pass the token to the main function. After an operation we give the token to next. It's unsafe to crete a new token.
From this, I think the safety become intuitive.
Cheers, N. On Tue, 31 Dec 2002, Ashley Yakeley wrote:
In article
, 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
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

G'day all. On Wed, Jan 01, 2003 at 01:15:09PM +0100, Nicolas.Oury wrote:
From this, I think the safety become intuitive.
Maybe. Using the OI module from Richard Kieburtz' paper, I can write this: -- Bootstrap into the OI comonad main :: IO () main = return $! comain stdOI -- The following are the OI functions which we use. -- stdGetChar :: OI () -> Char -- stdPutStrLn :: OI String -> () comain :: OI a -> () comain w = coeval (w .>> show (a,b) =>> stdPutStrLn) where a = coeval (w .>> () =>> stdGetChar) b = coeval (w .>> () =>> stdGetChar) Even though a and b are identical, they return different values. I see two possibilities: Either my intuition is way off, or the OI comonad breaks referential transparency. It's possible that it's a fault in the implementation. It was clearly intended as an example only, after all. Cheers, Andrew Bromage

In article <20030102225641.GA24187@smtp.alicorna.com>,
Andrew J Bromage
comain :: OI a -> () comain w = coeval (w .>> show (a,b) =>> stdPutStrLn) where a = coeval (w .>> () =>> stdGetChar) b = coeval (w .>> () =>> stdGetChar)
Even though a and b are identical, they return different values. I see two possibilities: Either my intuition is way off, or the OI comonad breaks referential transparency.
So is Kieburtz smoking crack, or are we writing OI-style programs incorrectly? One possibility is that comonads are useful for some things, but not for doing IO actions safely. -- Ashley Yakeley, Seattle WA

G'day all. On Thu, Jan 02, 2003 at 08:08:20PM -0800, Ashley Yakeley wrote:
So is Kieburtz smoking crack, or are we writing OI-style programs incorrectly?
I mailed him the example and asked. (I phrased the question a bit differently, though.)
One possibility is that comonads are useful for some things, but not for doing IO actions safely.
Another possibility is that comonads aren't as suited for "standard" pipes as monads. The problem only happens with an implicit file handle, as you have with getChar. Using hGetChar it's perfectly safe because the Handle is embedded in an OI comonad. Yet another possibility is that we haven't quite gotten the type signatures right on the OI primitives. A third possibility is that everything is okay and we're just missing something very obvious. Cheers, Andrew Bromage

In article <20030103042118.GA26720@smtp.alicorna.com>,
Andrew J Bromage
On Thu, Jan 02, 2003 at 08:08:20PM -0800, Ashley Yakeley wrote:
So is Kieburtz smoking crack, or are we writing OI-style programs incorrectly?
I mailed him the example and asked. (I phrased the question a bit differently, though.)
Did you ever get a reply? It's been three months... -- Ashley Yakeley, Seattle WA
participants (4)
-
Andrew J Bromage
-
Ashley Yakeley
-
Nicolas.Oury
-
peter@premise.demon.co.uk