gpt4 book ai didi

Haskells 弱头范式

转载 作者:行者123 更新时间:2023-12-02 01:57:34 25 4
gpt4 key购买 nike

我偶然发现了一些恼人的事情。我知道 haskell 适用于弱头范式(WHNF),我知道这是什么。在 ghci 中键入以下代码(据我所知,我正在使用命令 :sprint 将表达式简化为 WHNF。):

let intlist = [[1,2],[2,3]]
:sprint intlist

intlist = _这对我来说完全有意义。
let stringlist = ["hi","there"]
:sprint stringlist

stringlist = [_,_]这已经让我很困惑了。但是之后:
let charlist = [['h','i'], ['t','h','e','r','e']]
:sprint charlist

出人意料地给出 charlist = ["hi","there"]
据我了解 Haskell,字符串只不过是字符列表,这似乎可以通过检查类型来确认 "hi" :: [Char]['h','i'] :: [Char] .

我很困惑,因为根据我的理解,上面所有三个示例都或多或少相同(列表列表),因此应该减少到相同的 WHNF,即_。我错过了什么?

谢谢

最佳答案

请注意 :sprint 不是 将表达式简化为 WHNF。如果是这样,那么以下将给出 4而不是 _ :

Prelude> let four = 2 + 2 :: Int
Prelude> :sprint four
four = _

相反, :sprint获取绑定(bind)的名称,遍历绑定(bind)值的内部表示,并在使用 _ 时显示已经“评估的部分”(即构造函数的部分)作为未评估的 thunk 的占位符(即暂停的惰性函数调用)。如果该值完全未评估,则不会进行评估,甚至不会对 WHNF 进行评估。 (如果该值被完全评估,您将得到它,而不仅仅是 WHNF。)

您在实验中观察到的是多态与单态数字类型、字符串文字的不同内部表示与显式字符列表等的组合。基本上,您正在观察不同文字表达式如何编译为字节码的技术差异。因此,将这些实现细节解释为与 WHNF 有关,这会让您感到困惑。一般应该使用 :sprint仅作为调试工具,而不是作为了解 WHNF 和 Haskell 评估语义的一种方式。

如果你真的想了解 :sprint正在这样做,您可以在 GHCi 中打开一些标志以查看表达式实际上是如何处理的,因此最终编译为字节码:
> :set -ddump-simpl -dsuppress-all -dsuppress-uniques

在此之后,我们可以看到您的原因 intlist_ :
> let intlist = [[1,2],[2,3]]
==================== Simplified expression ====================
returnIO
(: ((\ @ a $dNum ->
: (: (fromInteger $dNum 1) (: (fromInteger $dNum 2) []))
(: (: (fromInteger $dNum 2) (: (fromInteger $dNum 3) [])) []))
`cast` <Co:10>)
[])

您可以忽略 returnIO和外部 :打电话,并专注于以 ((\ @ a $dNum -> ...开头的部分

这里 $dNumNum 的字典约束。这意味着生成的代码尚未解析实际类型 a在类型 Num a => [[a]] , 所以整个表达式仍然表示为一个函数调用,带有一个(字典)一个适当的 Num类型。换句话说,这是一个未经评估的重击,我们得到:
> :sprint intlist
_

另一方面,将类型指定为 Int ,并且代码完全不同:
> let intlist = [[1::Int,2],[2,3]]
==================== Simplified expression ====================
returnIO
(: ((: (: (I# 1#) (: (I# 2#) []))
(: (: (I# 2#) (: (I# 3#) [])) []))
`cast` <Co:6>)
[])
:sprint 也是如此输出:
> :sprint intlist
intlist = [[1,2],[2,3]]

类似地,文字字符串和显式字符列表具有完全不同的表示:
> let stringlist = ["hi", "there"]
==================== Simplified expression ====================
returnIO
(: ((: (unpackCString# "hi"#) (: (unpackCString# "there"#) []))
`cast` <Co:6>)
[])

> let charlist = [['h','i'], ['t','h','e','r','e']]
==================== Simplified expression ====================
returnIO
(: ((: (: (C# 'h'#) (: (C# 'i'#) []))
(: (: (C# 't'#)
(: (C# 'h'#) (: (C# 'e'#) (: (C# 'r'#) (: (C# 'e'#) [])))))
[]))
`cast` <Co:6>)
[])

以及 :sprint 中的差异输出表示 GHCi 认为表达式的哪些部分已评估(显式 : 构造函数)与未评估( unpackCString# thunk)的工件。

关于Haskells 弱头范式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60056065/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com