【问题标题】:Haskell: Defining strict dataHaskell:定义严格的数据
【发布时间】:2012-06-19 17:37:08
【问题描述】:

我一直在尝试创建一类“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

Ints 和Floats 定义实例很容易,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)

不幸的是,我遇到了一堆编译错误。我应该如何实现这个?

【问题讨论】:

    标签: haskell lazy-evaluation


    【解决方案1】:

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

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

    您将需要使用关联的数据类型,而不是类型同义词来添加所需的严格性注释。当你在那里时,你也可以为一些单态类型显式解包。

    之后,只添加 bang 模式的通用实例就很容易了。

    【讨论】:

      【解决方案2】:

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

      事实上,Control.Parallel.Strategies 中的 rdeepseq strategy 可能正是您正在寻找的。​​p>

      尽管名称中有“并行”,但实际上是 求值 策略,通过利用惰性来声明式指定计算,然后递归下降数据结构以选择性地应用像 seq 这样的函数, parpseq 到它的元素。

      【讨论】:

      猜你喜欢
      • 2016-04-11
      • 2012-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多