拥抱,功能及其计算方式

时间:2013-10-30 08:19:00

标签: haskell

我有一个输入:

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

输出是:

 [7,1,2,3]

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

我不知道优先级,7来自哪里?

3 个答案:

答案 0 :(得分:9)

你的问题包含两个问题,所以我会尽力简要回答这两个问题。

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人称为 thunks 。)然后它必须更深入,将其转化为

([ <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试图计算任何值,除非它绝对必须。它尽可能地尝试仅使用值的描述,而不是任何实际值。它在结束中执行所有必要的计算。

如果您没有要求列表的第一个值,那么永远不会计算

这是&#34;懒惰评估的意思。&#34;

答案 1 :(得分:4)

[ 8 `div` 2 + 1 .. ] !! 2 : [ 1 .. 3 ]
[ 4 + 1 .. ] !! 2 : [ 1 .. 3 ]
[ 5 .. ] !! 2 : [ 1 .. 3 ]
7 : [ 1 .. 3 ]
[7,1,2,3]

功能应用程序是从左到右。

答案 2 :(得分:2)

8 `div` 2 ≡ 4,因此[ 8 `div` 2 + 1 .. ]表示[ 5 .. ]。这是一个无限列表[5,6,7,8 ..]

list !! n - 从列表中取 n -th元素(从0开始),所以[5 .. ] !! 2 ≡ 7