dmaze ([personal profile] dmaze) wrote 2008-02-18 04:56 pm (UTC)

Rewriting this in terms of other arrows isn't too hard:

data (Arrow a) => CountArrow a b c = CountArrow (a (b,Int) (c,Int))

Mostly you can use the standard arr function to raise an arbitrary function into an arrow, but in particular implementing first requires using ghc's extended arrow syntax.

instance (Arrow a) => Arrow CountArrow a b c where
  arr f = ArrowCounted (arr (\(x,n) -> (f x,n)))
  (ArrowCounted f1) >>> (ArrowCounted f2) = ArrowCounted (f1 >>> f2)
  first (ArrowCounted f) =
    ArrowCounted (proc ((x,y),n) -> do (x',n') <- f -< (x,n)
                                       returnA -< ((x',y),n'))

In particular, it helps to read proc as "lambda", and the funky -< operator as appearing in between a function and its parameter; then this reads just like monadic "do" syntax.

(The other useful comment is that, having realized where the arrow could be useful at all, it's taken me a morning to come up with a couple of ways to write this class; the IO monad means that any Haskell work uses monads from day one and things like lists and Maybe are usefully monads, but it took years to actually get a handle on it.)


Post a comment in response:

This account has disabled anonymous posting.
If you don't have an account you can create one now.
HTML doesn't work in the subject.
More info about formatting

If you are unable to use this captcha for any reason, please contact us by email at support@dreamwidth.org