0

当我尝试这个时:

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确实可以让它消失,但我对使用该扩展程序持谨慎态度。在这种情况下,还有其他方法可以使事情正常进行吗?(最好不要过多地改变类型。)

4

1 回答 1

5

警告:我没有测试任何代码。

对我来说似乎最干净的方法是遵循Prelude.Extras-style 路径:

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

除非您注意要从左到右以及从右到左强制执行哪些向量,否则第二种方法似乎可能在向量融合方面表现不佳。

于 2016-01-05T06:55:21.220 回答