[personal profile] dmaze

A while ago, I achieved some Zen around the Monad type in Haskell; I could loosely describe it as "a value, with some extra class-specific goop that gets passed around", and I could write a state-tracking monad and a list-reading monad from scratch. So far, so good.

But the state-tracking monad is kind of icky to write. Let's say the state is an integer counter, and you want a getCount function that returns the current count and increments the counter. For the basic return function that promotes a value to a monad, you need to preserve the current value of the counter, so it needs to be a hidden function parameter, which means your monad type is really a function type.

data CountMonad a = CountMonad (Int -> (a,Int))
instance Monad CountMonad where
  return x = CountMonad (\n -> (x,n))
  (CountMonad f) >>= g = CountMonad (\n -> let (x,n') = f n
                                               (CountMonad g') = g x
                                           in g' n')
getCount :: CountMonad Int
getCount = CountMonad (\n -> (n,n+1))

Reasoning out in particular the >>= operator is a pain. I think this is where arrows come in. Since they deal in functions and not in values, it's easy to say "my arrow is a function with an extra hidden parameter":

data CountArrow b c = CountArrow ((b,Int) -> (c,Int))
instance Arrow CountArrow where
  arr f = CountArrow (\(x,n) -> (f x,n))
  (CountArrow f1) >>> (CountArrow f2) = CountArrow (f2 . f1)
  first (CountArrow f) = CountArrow (\((x,y),n) -> let (x',n') = f (x,n)
                                                   in ((x',y),n))
getCount :: CountArrow ignored Int
getCount = CountArrow (\(_,n) -> (n,n+1))

Is that "better"? It's easier to read, certainly, but a lot harder to figure out what's going on under the hood. I can rationalize Monad operations in terms of Maybe. Modern GHC provides some syntactic sugar for dealing with arrows which looks useful if hard to figure out from the documentation, plus there are some libraries; but the libraries helpfully point out that since normal functions (b -> c) are instances of Arrow I can extend things like my counted arrow as wrappers on arbitrary arrows.

So I'm not sure I have "the Zen" of arrows yet. But I can at least answer "what's the point" which is getting somewhere.

Date: 2008-02-18 05:12 pm (UTC)
From: [identity profile] kvarko.livejournal.com
Hey, Haskell! I didn't know that you knew Haskell! I use it every day at work. It's one of the highlights of my job :)

Sorry I don't have time to read your email deeper and comment, but just wanted to say: Haskell! (Presumably, [livejournal.com profile] fredrickegerman will have something to say on this post.)

Profile

dmaze

Expand Cut Tags

No cut tags
Page generated May. 31st, 2025 09:23 pm
Powered by Dreamwidth Studios