当我尝试这个:
import GHC.Generics (Generic) import Control.DeepSeq (NFData(..)) import Data.Vector.Generic (Vector) data Entry a = Entry !Bool a deriving (Generic, NFData) -- The variable @v@ is meant to be instantiated with a 'Vector' -- type. Most operations for the type have a @Vector v (Entry a)@ -- constraint. newtype DenseIntMap v a = DenseIntMap (v (Entry a)) instance NFData (v (Entry a)) => NFData (DenseIntMap v a) where rnf (DenseIntMap va) = rnf va
...我收到此错误:
/Users/casillas/GitHub/tau-sigma/src/TauSigma/Util/DenseIntMap.hs:53:10: Constraint is no smaller than the instance head in the constraint: Vector v (Entry a) (Use UndecidableInstances to permit this) In the instance declaration for ‘NFData (DenseIntMap v a)’ /Users/casillas/GitHub/tau-sigma/src/TauSigma/Util/DenseIntMap.hs:53:10: Constraint is no smaller than the instance head in the constraint: NFData (v (Entry a)) (Use UndecidableInstances to permit this) In the instance declaration for ‘NFData (DenseIntMap v a)’
使用UndecidableInstances
确实让它消失了,但我担心使用该扩展.在这种情况下,还有其他方法可以使事情发挥作用吗?(最好不要改变类型.)
警告:我还没有测试过这些代码.
对我来说最干净的方法是遵循一种Prelude.Extras
风格的方式:
class NFData1 f where rnf1 :: NFData a => f a -> ()
现在,您可以为每种矢量类型编写类似的内容
instance NFData1 V where rnf1 = rnf
然后
instance (NFData1 v, NFData a) => NFData (DenseIntMap v a) where ...
可满足当前代码更好的替代方法是想想v
作为一个Vector
明确的.而不是担心如何v a
更愿意强迫自己,而是通过折叠将自己的想法压在喉咙上:类似的东西
instance (Vector v a, NFData a) => NFData (DenseIntMap v a) where rnf = V.foldl' (\() e -> rnf e) ()
第二种方法似乎很可能在矢量融合方面表现不佳,除非你小心想要从左到右强制哪些矢量以及从右到左强制哪些矢量.