gpt4 book ai didi

Haskell长度+ map 解释?

转载 作者:行者123 更新时间:2023-12-03 15:05:52 25 4
gpt4 key购买 nike

因为我正在学习语言,所以我在玩 Haskell,我只是发现了一些我不理解的东西,我找不到解释。如果我尝试运行此代码:

map (`div` 0) [1,2,3,4]

我得到一个除以 0 的异常,这是预期的。
但是如果我运行这段代码:
length (map (`div` 0) [1,2,3,4])

我得到4!

我想知道为什么我在长度函数中进行映射时没有得到除以 0 的异常!

最佳答案

maplength函数可以这样定义:

map :: (a -> b) -> [a] -> [b]
map _ [] = []
map f (x:xs) = f x : map f xs

length :: [a] -> Int
length [] = 0
length (_:xs) = 1 + length xs

现在,让我们手动弄清楚为什么您的第二个示例会以这种方式工作。它是这样的:
length (map (`div` 0) (1:2:3:4:[]))
= length (1 `div` 0 : map (`div` 0) (2:3:4:[])) -- second map equation
= 1 + (length (map (`div` 0) (2:3:4:[]))) -- second length equation
= 1 + (length (2 `div` 0 : map (`div` 0) (3:4:[]))) -- second map equation
.
.
.
= 1 + (1 + (1 + (1 + length (map (`div` 0) []))))) -- second length equation
= 1 + (1 + (1 + (1 + length [])))) -- first map equation
= 1 + (1 + (1 + (1 + 0)))) -- first length equation
= 4 -- arithmetic

这里有什么诀窍?在 Haskell 中,计算表达式的过程称为强制它。强制表达式执行所需的最少工作,以便找出结果的最外层数据构造函数。作为其中的一部分,子表达式将仅在必要时强制实现目标。

所以在这个例子中,我们强制的最外层表达式是 length 的应用。功能。 length的定义有两种情况,一种使用 []列表构造函数和另一个使用 (:)构造函数,所以要申请 length我们需要弄清楚这两种情况中的哪一种适用于论证。由于参数在其最外层位置没有任何构造函数,我们必须强制它找出。这就是上面推导的第一行和第二行之间的步骤中发生的情况;我们强制 map通过查看其参数并选择第二个 map 子表达式方程。

但在那之后,我们拥有了确定 length 的两个方程中的哪一个所需的所有信息。适用,因此我们遵循“最外层优先”规则并应用适当的 length方程。在这种情况下,这将丢弃包含被零除的子表达式,这意味着永远不会强制子表达式,也永远不会触发错误。

然而,在您的第一个示例中,当您将表达式键入 GHCI 时,您隐含地要求解释器打印其结果。这要求它强制列表的主干访问其元素,并强制元素本身打印它们。因此,当您强制列表的第一个元素时,会发生除以零错误。

编辑:让我指出一个你可能没有注意到的细微差别。当我们在 GHCI 中尝试您的第一个示例时,这是 session 的结果:
*Main> map (`div` 0) [1,2,3,4]
[*** Exception: divide by zero

看到第二行开头那个孤独的开方括号了吗?这是正在打印的列表的左括号,在除以零错误发生之前。同样,请注意此示例中发生的情况:
*Main> map (20 `div`) [1,2,0,4]
[20,10,*** Exception: divide by zero

结果列表的前两个元素,甚至是分隔第二个元素和第三个元素的逗号,都可以成功打印,因为 Haskell 在需要打印之前不会尝试计算第三个列表元素。

关于Haskell长度+ map 解释?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23484270/

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