[Haskell-cafe] Mysterious monads

Isaac Dupree isaacdupree at charter.net
Sun May 27 10:09:21 EDT 2007


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Andrew Coppin wrote:
> Take a look at the following:
> 
>  data Writer o v = Writer [o] v
> 
>  instance Monad (Writer o) where
>    return v = Writer [] v
> 
>    (Writer os v) >>= f =
>      let (Writer os' v') = f v
>      in Writer (os ++ os') v'
> 
>  write :: o -> Writer o ()
>  write o = Writer [o] ()
> 
>  writes :: [o] -> Writer o ()
>  writes os = Writer os ()
> 
> By this code, I define a new monad where I can "write" stuff into a big
> list. (Although I notice this is going to get slower and slower as the
> list grows...)

Try the dlist library instead of plain lists, for the speed issue.

> For example,
> 
>  test = do
>    write 1
>    write 2
>    write 3
> 
> yields "Writer [1,2,3] ()".
> 
> Now, how do I implement the following?
> 
>  data Reader i v = Reader [i] v
> 
>  instance Monad (Reader i) where
>    return = ???
>    (>>=) = ???
> 
>  read :: Reader o o
> 
> such that a Reader is created with an initial list, and the read
> function fetches 1 element out of that list. That is, the expression "x
> <- read" will take the head element of the list and put it into x,
> keeping the tail to be read later.
> 
> (Oh yeah - and apparently that clashes with Prelude.read. Oh well!)

You could call it Unwriter/unwrite since it's in some way the opposite
in time of Writer (and since Reader monad conventionally refers to one
where the input state isn't consumed when it's read).

> I can't figure out how to implement this... The closest I managed was to
> make a Reader object also contain a function that tells (>>=) what to do
> to the Reader object you're binding against... But that seems to be
> horribly buggy.

you could try this (I haven't tested it but it looks okay to me)

newtype Unwriter i v = Unwriter ([i] -> (v, [i]))
instance Monad (Unwriter i) where
  return v = \_ -> v
  (Unwriter m) >>= f = Unwriter $ \i ->
    let (v, i') = m i
    in let Unwriter m' = f v
    in m' i'

unwrite :: Unwriter i i
- --well, what do you want it to do when there is nothing more left in the
input list?

Isaac
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFGWZERHgcxvIWYTTURAtN4AJ4zXKL97Pg9jttb27hPxJiPhibpjQCgp4AA
GWsftHiS6OL1VKINkZW1bGc=
=3T/G
-----END PGP SIGNATURE-----


More information about the Haskell-Cafe mailing list