【问题标题】:Memoization and typeclasses记忆和类型类
【发布时间】:2011-12-13 06:13:59
【问题描述】:

为了简单起见,我将使用这个人为的示例类(关键是我们有一些从方法派生的昂贵数据):

class HasNumber a where
  getNumber :: a -> Integer
  getFactors :: a -> [Integer]
  getFactors a = factor . getNumber

当然,我们可以做这个类的memoizing实现,比如:

data Foo = Foo {
  fooName :: String,
  fooNumber :: Integer,
  fooFactors :: [Integer]
}

foo :: String -> Integer -> Foo
foo a n = Foo a n (factor n) 

instance HasNumber Foo where
    getNumber = fooNumber
    getFactors = fooFactors

但要求手动将“因素”字段添加到任何将成为HasNumber 实例的记录似乎有点难看。下一个想法:

data WithFactorMemo a = WithFactorMemo {
    unWfm :: a,
    wfmFactors :: [Integer]
}

withFactorMemo :: HasNumber a => a -> WithFactorMemo a
withFactorMemo a = WithFactorMemo a (getFactors a)

instance HasNumber a => HasNumber (WithFactorMemo a) where
    getNumber = getNumber . unWfm
    getFactors = wfmFactors

不过,这将需要大量样板来将原始 a 的所有其他操作提升到 WithFactorMemo a

有什么优雅的解决方案吗?

【问题讨论】:

  • 我刚刚想到的另一个解决方案是让 factor 函数记忆,尽管如果getNumber 的结果是一些更大的数据结构,这将不太实用,并且(AFAIK)条目永远不会被垃圾收集(与我的问题中的两个解决方案相反)。

标签: haskell memoization


【解决方案1】:

解决方案如下:丢失类型类。我已经讨论过这个herehere。任何类型类TC a,其每个成员都将单个a 作为参数,与数据类型同构。这意味着HasNumber 类的每个实例都可以用这种数据类型表示:

data Number = Number {
    getNumber' :: Integer,
    getFactors' :: [Integer]
}

即通过这种变换:

toNumber :: (HasNumber a) => a -> Number
toNumber x = Number (getNumber x) (getFactors x)

Number 显然也是HasNumber 的一个实例。

instance HasNumber Number where
    getNumber = getNumber'
    getFactors = getFactors'

这个同构告诉我们这个类是变相的数据类型,它应该死掉。只需使用 Number 代替。最初如何做到这一点可能并不明显,但有了一点经验应该很快就会到来。例如,您的 Foo 类型变为:

data Foo = Foo {
    fooName :: String,
    fooNumber :: Number
}

您的记忆将免费提供,因为这些因素存储在 Number 数据结构中。

【讨论】:

  • 实际上,这也是我在您发布之前决定尝试的方法 :) 我同意将操作放入单一类型(Number 此处),但也许它仍然是一个好主意有一个class HasNumber a where numberDict :: a -> Number 和包装器getNumber = getNumber' . numberDict 等等。但是实际上必须将Number 存储在将成为HasNumber 的记录中,而不是在numberDict 实现中从整数创建Number(当然,这会让我们再次没有记忆) .
  • 在这种情况下,我强烈建议不要使用 typeclass,它只会妨碍您。只需具体建模,FP 工具箱更适合这种编程,该语言比类型类更擅长对数据类型进行抽象,而且它不会让你自欺欺人地认为你正在做 OO 建模(你是不是——如果你这样想,即使没有意识到,语言最终会限制你前进)。
猜你喜欢
  • 2015-03-05
  • 2012-12-22
  • 2019-01-20
  • 2021-02-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多