我在NFData
中的Control.DeepSeq
课时遇到了一些问题。我希望我的类型使用fmap
模块并行实现其Functor Control.Parallel.Strategies
。例如,在以下代码中,我收到错误,“无法推断(NFData b)...”。如果我使用rseq
代替rdeepseq
则没有问题,但我想尝试使用rdeepseq
。我在Ubuntu 11.04下运行GHC 6.12.3。
module Main where
import Control.Parallel.Strategies
import Control.DeepSeq
data Foo a = Foo Int [a]
deriving (Show,Eq)
instance Functor Foo where
fmap f (Foo i xs) = Foo i (map f xs `using` parList rdeepseq)
答案 0 :(得分:7)
抱歉,这是不可能的。如果您查看自己的fmap
,就可以看到它使用rdeepseq
a
,其中Foo
内的列表中的NFData
类型需要在班级Functor
中。但是没有地方可以附加这个约束,因为在实例声明中没有提到该类型变量。
使用{{1}}的非标准版本有各种变通办法,但其中没有一个是令人愉快的。
查看Haskell Type Constraints Unleashed建议的解决方案。
答案 1 :(得分:5)
您无法执行此操作的原因基本上与您无法为Monad
定义Data.Set
的实例的原因相同。
考虑Functor
类的定义:
class Functor f where
fmap :: (a -> b) -> (f a -> f b)
仿函数类要求所有类型b
的参数化,而在代码中使用rdeepseq
会将其限制为NFData b => b
。
解决方法是将评估与fmap
分开,例如为NFData
定义Foo
个实例:
instance Functor Foo where
fmap f (Foo i xs) = Foo i (map f xs)
instance NFData a => NFData (Foo a) where
rnf (Foo i xs) = i `seq` (xs `using` parList rdeepseq) `seq` ()