Proposal: Add Foldable helper to Control.DeepSeq

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` ()

+1 LGTM On 14.07.2016 05:16, David Feuer 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
-- Andreas Abel <>< Du bist der geliebte Mensch. Department of Computer Science and Engineering Chalmers and Gothenburg University, Sweden andreas.abel@gu.se http://www2.tcs.ifi.lmu.de/~abel/

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"
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` ()

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
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"
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

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"
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
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"
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
participants (3)
-
Andreas Abel
-
David Feuer
-
Edward Kmett