GithubHelp home page GithubHelp logo

deepseq's People

Contributors

barrucadu avatar bergmark avatar bgamari avatar bodigrim avatar chessai avatar cocreature avatar donsbot avatar duairc avatar ggreif avatar glguy avatar hvr avatar igfoo avatar int-index avatar josefs avatar martijnbastiaan avatar mboes avatar mixphix avatar pcapriotti avatar pepeiborra avatar phadej avatar ryanglscott avatar simonmar avatar sjakobi avatar tek avatar traviswhitaker avatar treeowl avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

deepseq's Issues

Add 'Whnf{,1,2}' (or some better name) newtype

newtype Whnf a = Whnf a
newtype Whnf1 f a = Whnf1 (f a)
newtype Whnf2 bi a b = Whnf2 (bi a b)

instance NFData (Whnf a) where rnf (Whnf a) = a `seq` ()
instance NFData1 (Whnf1 f) where liftRnf _ (Whnf1 as) = as `seq` ()
instance NFData2 (Whnf2 bi) where liftRnf2 _ _ (Whnf2 as) = as `seq` ()

Release for GHC 9.6.1

We will need a Hackage release in the next two weeks or so for GHC 9.6.1. Currently we are using 28f4d5b. A release from this commit would be greatly appreciated.

Add `rwhnf` helper for NF=WHNF instances

Here's an idea for a helper I wanted to document:

-- | Reduce to weak head normal form
--
-- Useful for defining 'NFData' for types for which NF=WHNF holds.
--
-- > data T = C1 | C2 | C3
-- > instance NFData T where rnf = rwhnf
rwhnf :: a -> ()
rwhnf !_ = ()

Changelog for 1.4.5.0 seems wrong

The changelog for 1.4.5.0 has:

Set infixr 0 for deepseq Makes infix use of 'deepseq' parse the same way as infix use of 'seq'

entry,

However:

% ghci-9.0.1
GHCi, version 9.0.1: https://www.haskell.org/ghc/  :? for help
Loaded GHCi configuration from /home/phadej/.ghci
Prelude> :m +Control.DeepSeq 
Prelude Control.DeepSeq> :i deepseq
deepseq :: NFData a => a -> b -> b 	-- Defined in ‘Control.DeepSeq’

and

deepseq-1.4.5.0 % cabal repl -w ghc-8.6.5
Resolving dependencies...
Build profile: -w ghc-8.6.5 -O1
In order, the following will be built (use -v for more details):
 - deepseq-1.4.5.0 (lib) (first run)
Configuring library for deepseq-1.4.5.0..
Preprocessing library for deepseq-1.4.5.0..
GHCi, version 8.6.5: http://www.haskell.org/ghc/  :? for help
Loaded GHCi configuration from /home/phadej/.ghci
[1 of 2] Compiling Control.DeepSeq  ( Control/DeepSeq.hs, interpreted )
[2 of 2] Compiling Control.DeepSeq.BackDoor ( Control/DeepSeq/BackDoor.hs, interpreted )
Ok, two modules loaded.
*Control.DeepSeq> :i de
decodeFloat  deepseq      denominator
*Control.DeepSeq> :i deepseq
deepseq :: NFData a => a -> b -> b
  	-- Defined at Control/DeepSeq.hs:235:1

but for 1.4.6.0:

deepseq-1.4.6.0 % cabal repl -w ghc-8.6.5  
Resolving dependencies...
Build profile: -w ghc-8.6.5 -O1
In order, the following will be built (use -v for more details):
 - deepseq-1.4.6.0 (lib) (first run)
Configuring library for deepseq-1.4.6.0..
Preprocessing library for deepseq-1.4.6.0..
GHCi, version 8.6.5: http://www.haskell.org/ghc/  :? for help
Loaded GHCi configuration from /home/phadej/.ghci
[1 of 2] Compiling Control.DeepSeq  ( Control/DeepSeq.hs, interpreted )
[2 of 2] Compiling Control.DeepSeq.BackDoor ( Control/DeepSeq/BackDoor.hs, interpreted )
Ok, two modules loaded.
*Control.DeepSeq> :i deepseq 
deepseq :: NFData a => a -> b -> b
  	-- Defined at Control/DeepSeq.hs:241:1
infixr 0 `deepseq`

ghc-8.2.0-rc1 compilation error

    Configuring deepseq-1.4.2.0...
    Preprocessing library for deepseq-1.4.2.0..
    Building library for deepseq-1.4.2.0..
    [1 of 1] Compiling Control.DeepSeq  ( Control/DeepSeq.hs, .stack-work/dist/x86_64-osx/Cabal-2.0.0.0/build/Control/DeepSeq.o )

    /private/var/folders/pq/xz5t60ld4v10j_tt7bd25rfhtzqwq8/T/stack92873/deepseq-1.4.2.0/Control/DeepSeq.hs:420:10: error:
        • Illegal instance declaration for ‘NFData TypeRep’
            (All instance types must be of the form (T t1 ... tn)
             where T is not a synonym.
             Use TypeSynonymInstances if you want to disable this.)
        • In the instance declaration for ‘NFData TypeRep’
        |
    420 | instance NFData TypeRep where
        |          ^^^^^^^^^^^^^^

deepseq-1.4.6.0 is not on Hackage

but already bundled with GHC-9.2.0-rc1.

(Also there is no changelog entry in the repository, or even a tag, which is what I was looking for).

Add method to help with strict containers

I propose an NFData method (by some name)

  whnfIsNf :: proxy a -> Bool
  whnfIsNf _ = False

Then we can have, for example,

instance NFData Integer where
  whnfIsNf _ = True
instance NFData a => NFData (Set a) where
  whnfIsNf _ = whnfIsNf (Proxy :: Proxy a)
  rnf
    | whnfIsNf (Proxy :: Proxy a)
    = \ !_ -> ()
    | otherwise
    = ....

This can avoid a bunch of unnecessary traversals.

Release for GHC 9.4.1

We are quickly approaching the final release for 9.4.1 and we do not plan to merge any further breaking changes. A prompt release would be greatly appreciated.

Add deeply strict liftM

Control.Monad offers <$!>. By analogy, I believe this package should offer

(<$!!>) :: (Monad m, NFData b) => (a -> b) -> m a -> m b
f <$!!> m = m >>= \x -> return $!! f x

($!!) seems to be implemented incorrectly

Current implementation of $!! is:

deepseq :: NFData a => a -> b -> b
deepseq a b = rnf a `seq` b

($!!) :: (NFData a) => (a -> b) -> a -> b
f $!! x = x `deepseq` f x
-- f $!! x = rnf x `seq` f x

However per documentation of seq and deepseq the second argument may be evaluated before the first one. This means that means that f x may be evaluated before rnf x.

Probably this should be changed to:

($!!) :: (NFData a) => (a -> b) -> a -> b
f $!! x = let f' = rnf x `seq` f in f' x

This way f may be evaluated before rnf x but f' x/f x will be evaluated after rnf x.

CI doesn't test GHC-7 versions

There are (so far successful) plans back to GHC-7.4

Either officially drop older GHC support and raise the base lower-bound, or please add CI for older GHCs too.

Let the list instance fuse

We can do something like

liftRnf f = foldr (\x r -> f x `seq` r) ()

This is useful when the list isn't going to be used again. In practice, this mostly occurs

  • in benchmarks
  • when the list is constructed solely to force any exception thunks in it.

For fun, here it is point free (I wouldn't use this):

liftRnf f = foldr (seq . f) ()

Review API for conditionally defined items

I notice/realise we expose some instances that are defined based on base version despite them existing before the given base version. This is obviously a problem as it would violate the package abstraction in a non-benign way.

Optimizing negations

If we have f :: b -> Void and g :: a -> b, we can get f . g :: a -> Void. But if we do this recursively, we'll get closures of increasing size. Would it make sense to offer something like this?

compNeg :: NFData a => (b -> Void) -> (a -> b) -> a -> Void
compNeg _ _ a = a `deepseq` error "Weird NFData instance or something"

remove instance NFData (a -> b)

I suggested to remove the instance NFData (a -> b) because it cannot be implemented properly. I think the proposal got broad support:
https://mail.haskell.org/libraries/2016-May/026961.html
We have still to decide whether to drop the instance or replace it by an unimplementable one. The latter one would have the advantage that people see that the instance is omitted by intention. We would need a major version bump. I can setup a pull request if you like.

Inefficient derived instance

Please see http://stackoverflow.com/questions/41884350/performance-difference-with-unpacking?noredirect=1#comment70951584_41884350

I have 2 datatypes for 4x4 matrix of Float:

  1. Matrix made of four four-element vectors of Float
  2. Matrix of 16 elements of Float

I suppose they have to be identical, but derived core code for NFData instance turns out to be different:

  1. 4 vectors of 4 elems:
-- RHS size: {terms: 5, types: 18, coercions: 0}
$fNFDataMatrix4x4f_$s$dmrnf :: Matrix4x4f -> ()
$fNFDataMatrix4x4f_$s$dmrnf =
  \ (eta_X8zo :: Matrix4x4f) ->
    case eta_X8zo
    of _
    { Matrix4x4f dt_d8x5 dt1_d8x6 dt2_d8x7 dt3_d8x8 dt4_d8x9 dt5_d8xa
                 dt6_d8xb dt7_d8xc dt8_d8xd dt9_d8xe dt10_d8xf dt11_d8xg dt12_d8xh
                 dt13_d8xi dt14_d8xj dt15_d8xk ->
    ()
    }
  1. Matrix of 16 elems:
-- RHS size: {terms: 70, types: 954, coercions: 0}
$fNFDataMatrix4x4f_$s$dmrnf :: Matrix4x4f -> ()
$fNFDataMatrix4x4f_$s$dmrnf =
  \ (eta_a8Bf :: Matrix4x4f) ->
    case eta_a8Bf
    of _
    { Matrix4x4f ww1_s8VG ww2_s8VH ww3_s8VI ww4_s8VJ ww5_s8VK ww6_s8VL
                 ww7_s8VM ww8_s8VN ww9_s8VO ww10_s8VP ww11_s8VQ ww12_s8VR ww13_s8VS
                 ww14_s8VT ww15_s8VU ww16_s8VV ->
    case $w$cfrom
           ww1_s8VG
           ww2_s8VH
           ww3_s8VI
           ww4_s8VJ
           ww5_s8VK
           ww6_s8VL
           ww7_s8VM
           ww8_s8VN
           ww9_s8VO
           ww10_s8VP
           ww11_s8VQ
           ww12_s8VR
           ww13_s8VS
           ww14_s8VT
           ww15_s8VU
           ww16_s8VV
    of _ { (# ww18_s8Yp, ww19_s8Yq #) ->
    case ww18_s8Yp of _ { :*: ww21_s8W3 ww22_s8Wj ->
    case ww21_s8W3 of _ { :*: ww24_s8W6 ww25_s8Wc ->
    case ww24_s8W6 of _ { :*: ww27_s8W9 ww28_s8Wa ->
    case ww25_s8Wc of _ { :*: ww30_s8Wf ww31_s8Wg ->
    case ww22_s8Wj of _ { :*: ww33_s8Wm ww34_s8Ws ->
    case ww33_s8Wm of _ { :*: ww36_s8Wp ww37_s8Wq ->
    case ww34_s8Ws of _ { :*: ww39_s8Wv ww40_s8Ww ->
    case ww27_s8W9 of _ { __DEFAULT ->
    case ww28_s8Wa of _ { __DEFAULT ->
    case ww30_s8Wf of _ { __DEFAULT ->
    case ww31_s8Wg of _ { __DEFAULT ->
    case ww36_s8Wp of _ { __DEFAULT ->
    case ww37_s8Wq of _ { __DEFAULT ->
    case ww39_s8Wv of _ { __DEFAULT ->
    case ww40_s8Ww of _ { __DEFAULT -> $fNFDataMatrix4x4f3 ww19_s8Yq }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }
    }

Upgrade Travis to haskell-ci

Currently, the Travis script is using a hacky setup that should probably be replaced with haskell-ci. I've made an effort to do so on the tests-in-separate-component branch. Because the dependencies of the test suite depend on deepseq, we have to put the tests in a separate .cabal file to work around haskell/cabal#5200, à la haskell/primitive#90 and ekmett/transformers-compat#33.

Alas, that branch currently is failing to build. It's always the same failure, when trying to build time:

cabal: can't find include file HsTimeConfig.h

I don't know how to fix this, so I'm giving up for now.

Instances for IORef/TVar/MVar and other mutable containers

I'd like to propose the following instances:

instance NFData (IORef a) where rnf x = seq x ()
instance NFData (TVar a) where rnf x = seq x ()
instance NFData (MVar a) where rnf x = seq x ()

I think forcing a mutable container should not force the contained value, since that is not really "part" of the data type, it is just referenced. The instances are nevertheless useful when working with APIs that expect NFData types, for example criterion.

Add instances for GHC.Generics data types

I'm currently in a situation where I want to rnf a value from an upstream library, but it doesn't define NFData instances.

It does, however, define a Generic instance. If there were NFData instances for the data types defined in GHC.Generics (eg U1 etc), I could write rnf . GHC.Generics.from. Alternatively, if deepseq exported its grnf definition, I could similarly write grnf . GHC.Generics.from.

Either of those would let me avoid something like an orphan instance etc. (Those can be harmless eg in exes or tests, but I try to avoid them in general.)

Are there pitfalls that would make exporting these instances/grnf a footgun for users, or would this merely provide users more options? Thanks.

Box helper to wrap types where WHNF = NF

I'd like a type that can be used to wrap values for which I want WHNF = NF. This is useful for satisfying NFData constraints with criterion for example.

newtype WHNF a = WHNF a
instance NFData (WHNF a) where rnf (WHNF a) = seq a ()

Of course, this data type should be given a better name. Maybe data instead of newtype would also be useful for even more laziness?

NFData1 helper

quoting http://permalink.gmane.org/gmane.comp.lang.haskell.libraries/24907, Henning writes

I have the type

   data NonEmpty f a = NonEmpty a (f a)

and want to declare an NFData instance in Haskell 98. With the
existing NFData class this is not possible because it requires a
(NFData (f a)) constraint which needs FlexibleContexts. A solution
would be an NFData1 class analogously to the classes in
transformers:Data.Functor.Classes:

  class NFData1 f where
     rnf1 :: NFData a => f a -> ()

  instance NFData1 [] where
     rnf1 = rnf

  instance (NFData1 f) => NFData1 (NonEmpty f) where
     rnf1 (NonEmpty x xs) = rnf (x, rnf1 xs)

  instance (NFData1 f, NFData a) => NFData (NonEmpty f a) where
     rnf = rnf1

Why deepseq infix revert?

1.4.6.1

Revert infixr 0 deepseq; this is a breaking change and requires a major version bump

It has been discussed in #56, https://mail.haskell.org/pipermail/libraries/2020-April/030361.html

I also remember (but fail to find discussions) that this change is one where not adhering to SHOULD in PVP is justified. The major bump in deepseq version library would (especially now) make people angry for no reason, and the change doesn't break anything, as deepseq combinator cannot be meaningfully chained with its current infixl 9.

Don't define the NFData TypeRep instance on GHC 8.2+

While testing some packages which depend on deepseq with GHC 8.2, I noticed that there is some breakage:

[1 of 1] Compiling Control.DeepSeq (...)

/tmp/stack4748/deepseq-1.4.2.0/Control/DeepSeq.hs:420:10: error:
    • Illegal instance declaration for ‘NFData TypeRep’
        (All instance types must be of the form (T t1 ... tn)
         where T is not a synonym.
         Use TypeSynonymInstances if you want to disable this.)
    • In the instance declaration for ‘NFData TypeRep’
    |
420 | instance NFData TypeRep where
    |          ^^^^^^^^^^^^^^

Using a CPP to conditionally include the instance should resolve the problem.

Fix GNFData instance for V1

Currently, we have

instance GNFData V1 where
  grnf = error "Control.DeepSeq.rnf: uninhabited type"

For old GHC, we should have

    grnf x = x `pseq` error "Control.DeepSeq.rnf: uninhabited type"

For newer GHC, we should have

    grnf x = case x of {}

Instance for `TVar`

This is a left-over issue from #6

As described in #6 (comment) by @glguy defining an instance for TVar is complicated since we'd lose {-# LANGUAGE Safe #-} by import TVar which seems undesirable, given all other instances can be imported safely.

Offer Foldable helper

It's possible to define a reasonable NFData instance for any Foldable type. We can offer a suitable rnf to help.

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

NFData for Proxy is not poly-kinded

rnf (Proxy :: Proxy 0) fails with this error:

    No instance for (deepseq-1.4.1.1:Control.DeepSeq.NFData (Proxy 0))
      arising from a use of ‘nf’

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.