[Haskell-cafe] deepSeq vs rnf

Chad Scherrer chad.scherrer at gmail.com
Mon Oct 23 01:12:44 EDT 2006


Interesting, I hadn't thought of the SYB approach. I still need to get
through those papers. Actually, I wonder if this idea would help with
something else I was looking into. It seems like it might occasionally
be useful to have a monad that is the identity, except that it forces
evaluation as it goes. Something like:

instance Monad Strict where
    return = Strict
    Strict x >>= f = rnf x `seq` f x

The problem is, this won't typecheck as-is, since not everything is an
instance of class NFData. I had been thinking of making a default
instance, something like

instance NFData a where
    rnf = id

and then using overlapping instances. But maybe boilerplate-scrapping
would make this cleaner? I'm still not sure what it can and can't do.

-Chad

> I agree, they are the same. The Strategies library also gives much
> more general operations for working with strictness and
> parallelisation. That library seems to need more love, I think it's a
> great idea, but it doesn't really get noticed all that much. The
> Hierarchical libraries documentation for it is a little lacking -- it
> doesn't even provide a reference or link to the paper, and many of the
> combinators, as well as the general idea of how to use it are
> undocumented from there. It also spuriously contains an Assoc
> datatype, which if I recall correctly, was an example from the paper,
> but doesn't really belong in the library as far as I can tell. It
> would also be really nice to see the list of instances for the NFData
> class expanded to include other datatypes in the libraries, possibly
> also with compiler support for deriving, since it's mostly
> boilerplate.
>
> Speaking of boilerplate and the scrapping thereof, Data.Generics could
> theoretically also be used to write a relatively generic rnf/deepSeq,
> but in my attempts, it seems to be much much slower than using a
> specific normal form class. Here's my code from quite a while back. As
> I recall, it's semantically correct, but ran about an order of
> magnitude slower. There might be a much better way to do it, I don't
> really know Data.Generics all that well.
>
> rnf :: (Data a) => a -> ()
> rnf x = everything (\x y -> x `seq` y) (\x -> x `seq` ()) x
>
> deepSeq x y = rnf x `seq` y
>
> f $!! x = rnf x `seq` f x
>
>  - Cale


More information about the Haskell-Cafe mailing list