gpt4 book ai didi

haskell - 拥抱,功能及其计算方式

转载 作者:行者123 更新时间:2023-12-02 14:26:44 27 4
gpt4 key购买 nike

我有一个输入:

 [ 8 `div` 2 + 1 .. ] !! 2 : [ 1 .. 3 ]


输出为:

 [7,1,2,3]


但是.. Haskell首先计算什么?

我不知道优先级,哪七个是哪里来的?

最佳答案

您的问题包含两个问题,因此,我将尽力简短地回答两个问题。

1. Haskell中的操作顺序

给定诸如2 + 4 * 3的表达式,Haskell是先计算2+4然后乘以3,还是先计算4*3然后加2?您可能已经猜到了,4*3首先。

您怎么知道哪个先出现?您在相关操作员的文档和/或源代码中查找。或者,您可以通过实验弄清楚。在你的例子中

[ 8 `div` 2 + 1 .. ] !! 2 : [ 1 .. 3 ]


我从经验中知道,如果要在所有地方加上括号,它们将如下所示:

([ ((8 `div` 2) + 1) .. ] !! 2) : [ 1 .. 3 ]


找出优先顺序

为了正确解决这个问题,您需要打开 ghci,然后键入

:info (+)


例如,它将说出类似

infixl 6 (+)


如果我们也为其他操作员执行此操作,则可以为我们构建一个整洁的表。

infixl 7 `div`
infixl 6 +
infixr 5 :
infixl 9 !!


ghci没有为 (!!)讲任何话,但是我去了 source code for list operations in the Prelude并找到了准确表达我在表中显示的内容的行。然后,您可以假定列表的工作原理类似于括号,因此 []方括号中的内容在其前面的内容之前。

优先级如何工作

现在, infix声明中运算符名称前面的数字表示运算符的优先级高–数字越高,它在其他事物之前的作用就越大。例如,在这种情况下,

infixl 7 `div`
infixl 6 +


这意味着 `div`+之前,实际上在表达式中

8 `div` 2 + 1


我们发现Haskell将结果计算为

(8 `div` 2) + 1


因为 `div`具有更高的优先级。如果对表达式的其余部分执行此操作,则将得到与该答案开头相同的括号。

但是,您通常不必太在意,因为您写的Haskell越多,您对它的工作方式就会越有感觉。通常,如果您弄错了,您还会得到一个类型错误,以提醒您您弄错了。如有疑问,请尝试使用括号和不使用 ghci两者,然后看看哪一个给出正确的答案。

2. Haskell中的计算顺序

到目前为止,我已经回答了“ Haskell如何解释一个表达式?”这一问题。实际计算的顺序是一个完全不同的问题。大多数编程语言都首先计算内部括号-Haskell恰恰相反!

给定表达式

([ ((8 `div` 2) + 1) .. ] !! 2) : [ 1 .. 3 ]


Haskell一开始只会将其视为

<something>


然后当您要求价值时,它会吟一点,并意识到这是在说

<something> : <something>


它将意识到需要进一步计算才能给您带来价值,因此它将扩展为

(<something> !! <something>) : [ 1 .. 3 ]


(顺便说一下,这些 <something>通常被Haskell的人称为thunk。)然后,它必须更深入,将其转变为

([ <something> .. ] !! 2) : [ 1 .. 3 ]


然后,它需要此列表的第二个元素,因此它将尽可能多地扩展列表。

([ <something>
, (<something> + 1)
, (<something> + 2) .. ] !! 2) : [ 1 .. 3 ]


然后,它可以减小 !!,返回列表的第三个元素(索引为2),因此整个列表消失,并被第三个元素替换。

(<something> + 2) : [ 1 .. 3 ]


然后可以减少 :,因此结果是一个列表。

[ <something + 2>, 1, 2, 3 ]


在这一点上,它最终必须弄清楚 <something>是什么,因此可以追溯到它的定义并将其扩展为

[ (<something> + 1) + 2, 1, 2, 3 ]


然后

[ ((8 `div` 2) + 1) + 2, 1, 2, 3 ]


然后开始计算第一个元素的实际值,为您

[ (4 + 1) + 2, 1, 2, 3 ]
[ 5 + 2, 1, 2, 3 ]
[ 7, 1, 2, 3 ]


可以避免的是,Haskell除非绝对必要,否则不尝试计算任何值。它尝试尽可能只使用值的描述,而不使用任何实际值。最后,它执行所有必要的计算。

如果您不要求列表的第一个值,则永远不会计算得出。

这就是“惰性评估”的含义。

关于haskell - 拥抱,功能及其计算方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19677058/

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