【问题标题】:Using fmap with Parallel.Strategies gives NFData error将 fmap 与 Parallel.Strategies 一起使用会导致 NFData 错误
【发布时间】:2011-05-26 00:06:26
【问题描述】:

我在使用 Control.DeepSeq 中的 NFData 类时遇到了一些问题。我希望我的类型使用 Control.Parallel.Strategies 模块并行实现其 Functor fmap。例如,在下面的代码中,我在开始“无法推断(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)

【问题讨论】:

    标签: haskell parallel-processing


    【解决方案1】:

    抱歉,这是不可能的。如果您查看您的fmap,您会发现它使用了rdeepseq,它需要Foo 内部列表中的a 类型才能在类NFData 中。但是根本没有地方可以附加这个约束,因为在实例声明的任何地方都没有提到这个类型变量。

    使用非标准版本的Functor 有多种解决方法,但没有一个是令人愉快的。

    查看Haskell Type Constraints Unleashed 以获得建议的解决方案。

    【讨论】:

      【解决方案2】:

      您不能这样做的原因与您不能为Data.Set 定义Monad 的实例的原因基本相同。

      考虑Functor类的定义:

      class Functor f where
          fmap :: (a -> b) -> (f a -> f b)
      

      仿函数类需要所有类型b 的参数化,而在您的代码中使用rdeepseq 试图将其限制为NFData b => b

      一种解决方法是将评估与fmap 分开,例如为Foo 定义一个NFData 实例:

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

      【讨论】:

      • 太棒了!您知道为什么以下内容没有给出undefined吗? fmap (+1) (Foo 0 [1,2,undefined]) `deepseq` 3
      • @user643722:我还没有和Control.Parallel.Strategies 亲密,但似乎parList 在只评估最外面的(:) 时不会触发元素评估(使用seq在这个例子中)。将第二个 seq 更改为 deepseq 会按预期提供 undefined
      猜你喜欢
      • 2011-06-30
      • 2013-11-11
      • 2014-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-22
      • 2015-02-23
      相关资源
      最近更新 更多