搞笑哈斯克尔行为:三个数字的最小函数,包括一个负数 [英] Funny Haskell Behaviour: min function on three numbers, including a negative

查看:117
本文介绍了搞笑哈斯克尔行为:三个数字的最小函数,包括一个负数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我收到了一些非常有趣的行为,我想知道为什么会发生这种情况。

我一直在玩GHCi中的一些Haskell函数。 p>

我意识到函数 min 只能与两个值一起使用。然而,当我使用三个值时,在我的情况下

  min 1 2 -5 

  -4 $ > 

b $ b

作为我的结果。



为什么会这样

解决方案

您得到的结果是因为这个表达式:

  min 1 2 -5 

解析为像括号一样这:

 (min 1 2)-5 

与此相同:

  1 -5 

与此相同:

  1  -  5 

当然是-4。



在Haskell中,函数应用程序是最紧密绑定的操作,但它不是贪婪的。事实上,即使像 min 1 2 这样看起来很简单的表达式实际上会导致两个独立的函数调用:函数 min 是首先用单个值1调用;该函数的返回值是一个新的匿名函数,它将返回1和其单个参数之间的较小值。这个匿名函数然后用2的参数调用,当然返回1.因此,一个更准确的完全加括号的代码版本是这样的:

 ((min 1)2) -  5 

值,您需要将两个呼叫链接到 min

  min (min 1 2)(-5)

从技术上讲,上面的代码实际上导致了根据前面概述的逻辑单独调用函数 - 使得显式类似于下面的代码,但可以认为它只是对 min :

 (min((min 1)2))(-5)

围绕 -5 的圆括号确保 - 被解释为前缀否定而不是中缀减法。一般来说,如果你在Haskell中有一个文字负数,括号是必须的。在某些情况下,您可以将它们关闭,但使用它们会使代码阅读器变得更加清晰。

更一般地说,您可以让Haskell通过以下方式为您链接:将一个折叠应用到列表中,然后可以包含尽可能多的数字:

  foldl1 min [1,2, - 5] 

(请注意,列表中的项目是您可以离开圆括号的上下文之一)



foldl1 fun list 表示获取 list 的前两项并调用 fun ,然后将该调用的结果和下一项 ,然后在这两个值上调用 fun ,然后将该调用的结果和列表的下一个项目......等等,直到没有更多 list ,此时最后一次调用 fun 的值返回给原始调用者。



但是,具有预定义的预折叠等价物的函数是其中之一,而 min 列表版本称为 最低

 最小值[1,2,-5] 

行为与我的 foldl1 上面的解决方案;特别是,如果交给一个空列表,这两者都会抛出一个错误。



感谢JohnL提醒我存在 minimum


I've been playing around with some Haskell functions in GHCi.

I'm getting some really funny behaviour and I'm wondering why it's happening.

I realized that the function min is only supposed to be used with two values. However, when I use three values, in my case

min 1 2 -5

I'm getting

-4

as my result.

Why is that?

解决方案

You are getting that result because this expression:

min 1 2 -5

parses as if it were parenthesized like this:

(min 1 2) -5

which is the same as this:

1 -5

which is the same as this:

1 - 5

which is of course -4.

In Haskell, function application is the most tightly-binding operation, but it is not greedy. In fact, even a seemingly simple expression like min 1 2 actually results in two separate function calls: the function min is first called with a single value, 1; the return value of that function is a new, anonymous function, which will return the smaller value between 1 and its single argument. That anonymous function is then called with an argument of 2, and of course returns 1. So a more accurate fully-parenthesized version of your code is this:

((min 1) 2) - 5

To find the minimum of three values, you need to chain together two calls to min:

min (min 1 2) (-5)

Technically, the above code actually results in four separate function calls, per the logic outlined earlier - making that explicit would look something like the code below, but it's fine to think of it as just two calls to min:

(min ((min 1) 2)) (-5)

The parentheses around -5 ensure that the - is interpreted as prefix negation instead of infix subtraction. In general, if you have a literal negative number in Haskell, the parentheses are necessary. In some cases you can leave them off, but using them makes things clearer for the reader of your code.

More generally, you could let Haskell do the chaining for you by applying a fold to a list, which can then contain as many numbers as you like:

foldl1 min [1, 2, -5]

(Note that an item in a list is one of the contexts where you can leave the parentheses off the literal negative number.)

The call foldl1 fun list means "take the first two items of list and call fun on them. Then take the result of that call and the next item of list, and call fun on those two values. Then take the result of that call and the next item of the list..." And so on, continuing until there's no more list, at which point the value of the last call to fun is returned to the original caller.

There are several functions that have predefined pre-folded equivalents, however, and min is one of them; the list version is called minimum:

minimum [1, 2, -5]

That behaves exactly like my foldl1 solution above; in particular, both will throw an error if handed an empty list.

Thanks to JohnL for reminding me of the existence of minimum.

这篇关于搞笑哈斯克尔行为:三个数字的最小函数,包括一个负数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆