Haskell:定义严格的数据

时间:2012-06-19 17:37:08

标签: haskell lazy-evaluation

我一直试图制作一类'Strictable'类型。原因是我想要定义这样的东西:

foldl'' f z = foldl' f (make_strict z)

因此,在fold''类型上使用strictable时,不会有未评估的thunk。

所以我从以下开始:

{-# LANGUAGE TypeFamilies #-}

class Strictable a where
  type Strict a :: *
  make_strict :: a -> Strict a

IntFloat定义实例非常简单,foldl'已经可以正常使用,所以没有任何事情要做。

instance Strictable Int where
  type Strict Int = Int
  make_strict = id

instance Strictable Float where
  type Strict Float = Float
  make_strict = id

这是棘手的部分。 foldl'仅解包最外层的构造函数,因此,例如,使用foldl',您仍然可以获得空间泄漏。我想用普通的一对来创建一对严格的对。所以我尝试了这个:

instance (Strictable a, Strictable b) => Strictable (a, b) where
  type Strict (a, b) = (! Strict a, ! Strict b)
  make_strict (x1, x2) = (make_strict x1, make_strict x2)

不幸的是我收到了一堆编译错误。我该如何实现呢?

2 个答案:

答案 0 :(得分:3)

你在寻找like this的东西吗?即使用关联的数据,而不是输入同义词。

instance AdaptPair Bool Bool where
  data Pair Bool Bool = PBool {-# UNPACK #-}!Int {-# UNPACK #-}!Int

  fst (PBool x _) = Prelude.toEnum x
  snd (PBool _ x) = Prelude.toEnum x
  curry f x y    =  f (PBool (Prelude.fromEnum x) (Prelude.fromEnum y))

您需要使用关联的数据类型而不是类型同义词来添加所需的严格注释。当你在那里的时候,你也可以明确解开一些单一类型的东西。

之后添加爆炸模式的通用实例很容易。

答案 1 :(得分:2)

如果我正确理解了您的问题,并且我对parallel strategies(PDF链接)的理解不会让我失望,那么并行策略可以直接实现您的make_strict;请参阅parallel package了解API和并行策略的实现。

事实上,来自rdeepseq strategyControl.Parallel.Strategies可能正是您所寻找的。

尽管名称中存在“并行”,但实际上评估策略是通过利用惰性来声明性地指定计算然后以递归方式下降数据结构以选择性地应用{{1}之类的函数来实现的。 },seqpar到其元素。