[Haskell-cafe] help for the usage on mfix

Ryan Ingram ryani.spam at gmail.com
Wed Feb 23 15:31:05 CET 2011

Just write a loop:

> let loop gs gu
>    | Just z <- find_obj gu usyms = do
>            ...
>            (gs', gu') <- handle_obj_ar ...
>            loop gs' gu'
>    | otherwise = return (gs,gu)
> (gs, gu) <- loop def undef

mfix is for when you have mutually recursive data but you want the IO
operation to only execute once.  It's most useful when working with some
sort of lazy data structure like a list, tree, or graph.

I can't come up with an example for IO off the top of my head, but for the
ICFP contest this year I wrote a gate/wire embedded language which had code
that looks like this:

sample wireIn = do
       (wireOut,a) <- gate (wireIn,d)
       (d,b) <- gate (a, b)
   return wireOut

which would create a circuit like this:

---in->[  ]------out-------->
  +-d->[  ]--a-->[  ]-d---+
  |         +-b->[  ]-b-+ |
  |         +-----------+ |

This code translates to something like

sample wireIn = do
    (wireOut, _, _, _) <- mfix $ \(_, b, d) -> do
        (wireOut', a) <- gate (wireIn, d)
        (d', b') <- gate (a,b)
        return (wireOut', b', d')
    return wireOut'

The key is that gate was lazy in its arguments; the gate didn't care what
its input wires were, it just needed them to exist at the time you asked for
the entire circuit definition.  mfix says 'run the *effects* in this code
once, but the *data* might be recursive'.

  -- ryan
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20110223/c04d165d/attachment.htm>

More information about the Haskell-Cafe mailing list