haskell - 惰性和多态值

标签 haskell polymorphism lazy-evaluation memoization

(对于以下内容,将 ShowRead 简化为

class Show a where show :: a -> String
class Read a where read :: String -> a

并假设 read从未失败。)

众所周知,可以制作一种存在类型的形式
data ShowVal where
    ShowVal :: forall a. Show a => a -> ShowVal

然后构造一个“异构列表”:: [ShowVal] , 如
l = [ShowVal 4, ShowVal 'Q', ShowVal True]

众所周知,这是相对无用的,因为相反,可以
只需构建一个列表:: [String] , 如
l = [show 4, show 'Q', show True]

这完全是同构的(毕竟,唯一可以用ShowValshow它)。

懒惰使这特别好,因为对于列表中的每个值,show 的结果自动内存,所以没有 String计算超过
一次(并且根本不计算未使用的 String s)。

一个 ShowVal等价于存在元组 exists a. (a -> String, a) ,
其中函数是Show字典。

可以为 Read 制作类似的构造。 :
data ReadVal where
    ReadVal :: (forall a. Read a => a) -> ReadVal

请注意,因为 read它的返回值是多态的,ReadVal
普遍的而不是存在的(这意味着我们在
全部,因为 Haskell 具有一流的通用性;但我们将在这里使用它
突出显示与 Show 的相似之处)。

我们也可以列个 list :: [ReadVal] :
l = [ReadVal (read "4"), ReadVal (read "'Q'"), ReadVal (read "True")]

就像 Show , 列表 :: [ReadVal]与列表 :: [String] 同构,

l = ["4", "'Q'", "True"]

(我们总能得到原来的String
newtype Foo = Foo String
instance Read Foo where read = Foo

因为Read类型类是开放的。)

一个 ReadVal相当于一个通用函数forall a. (String -> a) -> a(CPS 风格的表示)。这里 Read字典由用户提供
ReadVal而不是生产者,因为返回值是
多态而不是参数。

然而,在这两种表示中,我们都没有得到自动
我们在 String 中获得的内存用 Show 表示.让我们这么说read因为我们的类型是一个昂贵的操作,所以我们不想计算它
在同一个 String同一类型不止一次。

如果我们有一个封闭的类型,我们可以这样做:
data ReadVal = ReadVal { asInt :: Int, asChar :: Char, asBool :: Bool }

然后使用一个值
ReadVal { asInt = read s, asChar = read s, asBool = read s }

或类似的规定。

但在这种情况下——即使我们只使用 ReadVal作为一种类型——String每次使用该值时都会被解析。有没有简单的方法
在保留 ReadVal 的同时获取内存多态?

(让 GHC 自动完成,类似于 Show 的情况,将是
理想,如果有可能的话。更明确的内存方法——
也许通过添加 Typeable约束? ——也可以。)

最佳答案

Laziness makes this particularly nice, because for each value in the list, the result of show is memoized automatically, so no String is computed more than once (and Strings that aren't used aren't computed at all).



这个前提是不正确的。引擎盖下没有神奇的备忘录表。

懒惰意味着不需要的东西,不计算。这并不意味着所有计算值都是共享的。您仍然必须引入显式共享(通过您自己的表)。

关于haskell - 惰性和多态值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10168939/

相关文章:

java - 多态性:构造函数不接受参数

C++ 2a - 多态范围

c++ - C++ 类中的任意数据类型

AND() 和 OR() 的 Excel 惰性求值

stream - 难以理解/可视化SICP流汉明数程序

java - Java 8 会有惰性求值吗?

haskell - 为什么这个平均函数在 haskell 中不起作用?

haskell - Karplus-Strong Algo 中的递归反馈 - 箭头

haskell - 如何通过 Haskell 的 optparse-applicative 使用具有多个值的选项

haskell - 如果某些东西不是 Haskell 中的列表