I've put up a pull request at https://github.com/haskell/deepseq/pull/18 adding rnfFoldableLTR and rnfFoldableRTL, and documenting when they can (and when they cannot) produce good NFData instances. The implementations are monoid based, but use slightly different monoid definitions than originally proposed so as to produce extremely clean Core for GHC >= 7.8 even without specialization. Edward: similar functions could also be written for Bifoldable. I'd be happy to send a PR to bifunctors if you'd like.


On Jul 14, 2016 3:09 PM, "Edward Kmett" <ekmett@gmail.com> wrote:
The monoid may be more efficient if the Foldable is constructed to take advantage of internal sharing.

-Edward

On Thu, Jul 14, 2016 at 11:52 AM, David Feuer <david.feuer@gmail.com> wrote:

I guess these are equivalent to the simpler expressions

rnfLTR = foldl' (const rnf) ()
rnfRTL = foldr' (\x _ -> rnf x) ()


On Jul 13, 2016 11:16 PM, "David Feuer" <david.feuer@gmail.com> wrote:
As I describe in https://github.com/haskell/deepseq/issues/17 it is
possible to implement an NFData instance for any Foldable type, and we
can offer a function to help do that:

data Unit = Unit

instance Monoid Unit where
  mempty = Unit
  Unit `mappend` Unit = Unit -- strict in both arguments, unlike ()

rnfFoldable :: (Foldable f, NFData a) => f a -> ()
rnfFoldable xs = foldMap (\x -> rnf x `seq` Unit) xs `seq` ()

This could be used like so:

instance NFData a => NFData (F a) where
  rnf = rnfFoldable

This version forces from left to right. It would be possible to offer
another version that forces from right to left:

data Unit2 = Unit2

instance Monoid Unit2 where
  mempty = Unit2
  x `mappend` Unit2 = x `seq` Unit2

rnfFoldableRTL :: (Foldable f, NFData a) => f a -> ()
rnfFoldableRTL xs = foldMap (\x -> rnf x `seq` Unit2) xs `seq` ()

_______________________________________________
Libraries mailing list
Libraries@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries