Haskell:使用 $ 的函数应用
在下面的代码片段中,您可以看到我用 Haskell 编写的两个 collatz 函数。对于递归应用程序,我在第一个示例 (collatz) 中使用括号来获得正确的优先级。
由于我刚刚学习了 $ 的函数应用,我尝试使用那个东西重写函数(collatz')。但是,我遇到以下错误:
无法匹配预期类型“[a]” 针对推断类型 `a1 -> [a1]' 在 `(:)' 的第二个参数中,即 `collatz'' 在 `($)' 的第一个参数中,即 `n : collatz'' 在表达式中: n : collatz' $ n `div` 2
collatz :: (Integral a) => a -> [a]
collatz 1 = [1]
collatz n | even n = n : collatz (n `div` 2)
| otherwise = n : collatz (n * 3 + 1)
collatz' :: (Integral a) => a -> [a]
collatz' 1 = [1]
collatz' n | even n = n : collatz' $ n `div` 2
| otherwise = n : collatz' $ n * 3 + 1
这对我来说很奇怪,这不起作用。所以我尝试了一个类似的有效示例:
True : [even $ 3 `div` 3]
如果有人可以看一下它并告诉我我做错了什么,我将不胜感激。
In the following snippet, you can see my two collatz functions I wrote in Haskell. For the recursive application I used parentheses in the first example (collatz) to get the right precedence.
As I have just learnt function application with $, I tried to rewrite the function (collatz') using that thing. However, I encounter the following error:
Couldn't match expected type `[a]'
against inferred type `a1 -> [a1]' In the second argument of `(:)', namely `collatz'' In the first argument of `($)', namely `n :
collatz'' In the expression: n : collatz' $ n `div` 2
collatz :: (Integral a) => a -> [a]
collatz 1 = [1]
collatz n | even n = n : collatz (n `div` 2)
| otherwise = n : collatz (n * 3 + 1)
collatz' :: (Integral a) => a -> [a]
collatz' 1 = [1]
collatz' n | even n = n : collatz' $ n `div` 2
| otherwise = n : collatz' $ n * 3 + 1
It seamed weird to me that this didn't work. So I tried a similar example that worked:
True : [even $ 3 `div` 3]
I'd appreciate it, if somebody could take a look at it and tell me what I'm doing wrong.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
$
的优先级低于:
(以及其他任何内容),因此您的函数解析为这会导致您的类型错误。
:
的第二个参数需要一个列表,但您传递的是 collatz 函数。如果您仍然想避免 3n+1 部分周围的括号,您可以执行类似以下操作,
尽管这些不一定比原来的更清晰。如果您想知道,第一个示例中的
(n:)
是\x ->; 的语法糖。 n:x
$
has lower precedence then:
(and also anything else) so your function is parsing asThis leads to your type error. The second argument of
:
expects a list but you are passing the collatz function instead.If you still want to avoid the parenthesis around the 3n+1 part you can do something like the following
although these are not necessarily cleaner then the original. In case you are wondering, the
(n:)
in the first example is a syntactic sugar for\x -> n : x
既然其他人已经解释了问题是什么,我想我会解释一下你如何自己解决这个问题。 (授人以渔等等...)
注意错误消息的这一部分:
这是注意到这是一个优先级问题的线索。 GHC 告诉您
n : collatz'
被解析为$
的第一个参数,而您期望第一个参数只是collatz'
>。此时,我通常启动 GHCi 并使用
:info
命令检查涉及的优先级:它说
:
的优先级是 5,而的优先级>$
为 0,这解释了为什么:
比$
绑定“更紧密”。Since others have explained what the problem is, I figured I'll explain how you could have figured this out on your own. (Teaching a man to fish and so on...)
Note this part of the error message:
That's the clue to noticing that this is a precedence problem. GHC is telling you that
n : collatz'
was parsed as the first argument of$
, while you were expecting the first argument to be justcollatz'
.At this point, I usually fire up GHCi and check the precedences involved using the
:info
command:It says that the precendence of
:
is 5, while the precedence of$
is 0, which explains why the:
is binding "tighter" than the$
.:
的结合力比$
更强。考虑 注意解析器找到的“表达式”
1 : f
;它看到的是(1 : f) $2
而不是1 : (f $2)
。:
binds more strongly than$
. ConsiderNote the "expression"
1 : f
found by the parser; it sees(1 : f) $ 2
rather than1 : (f $ 2)
.正如@missingno 所说,这是一个运算符优先级问题。你可以像这样重写它
但这显然不会给你带来太多好处,因为你仍然有括号。
As @missingno stated, it's an operator precedence problem. You could rewrite it like this
But that obviously doesn't buy you much, because you still have parenthesis.