Haskell:带有$的函数应用程序

ret*_*hab 11 haskell ghci

在下面的代码片段中,您可以看到我在Haskell中编写的两个collat​​z函数.对于递归应用程序,我在第一个示例(collat​​z)中使用括号来获得正确的优先级.

由于我刚刚用$学习了函数应用程序,我试图用这个东西重写函数(collat​​z').但是,我遇到以下错误:

无法匹配期望类型`[a]'与推断类型`a1 - > [a1]'在`(:)'的第二个参数中,即``collat​​z''在`($)'的第一个参数中,即`n:collat​​z''在表达式中:n:collat​​z'$ 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
Run Code Online (Sandbox Code Playgroud)

它对我来说很奇怪,这不起作用.所以我尝试了一个类似的例子:

True : [even $ 3 `div` 3]
Run Code Online (Sandbox Code Playgroud)

我很感激,如果有人可以看看它并告诉我我做错了什么.

hug*_*omg 18

$具有较低的优先级:(以及其他任何东西),因此您的函数正在解析为

(n : collatz') $ (n `div` 2)
Run Code Online (Sandbox Code Playgroud)

这会导致您的类型错误.:期望列表的第二个参数,但您传递的是collat​​z函数.

如果您仍想避免3n + 1部分周围的括号,您可以执行以下操作

(n:) . collatz' $ n `div` 2
n : (collatz' $ n `div` 2)
Run Code Online (Sandbox Code Playgroud)

虽然这些不一定比原版更清洁.如果你想知道,(n:)在第一个例子中是一个语法糖\x -> n : x


ham*_*mar 10

由于其他人已经解释了问题所在,我想我会解释你如何能够自己解决这个问题.(教一个人钓鱼等等......)

请注意错误消息的这一部分:

在'($)'的第一个参数中,即'n:collat​​z''

这是发现这是一个优先问题的线索.GHC告诉你,它n : collatz'被解析为第一个参数$,而你期望第一个参数是公正的collatz'.

此时,我通常会启动GHCi并使用该:info命令检查所涉及的优先级:

> :info :
data [] a = ... | a : [a]   -- Defined in GHC.Types
infixr 5 :
> :info $
($) :: (a -> b) -> a -> b   -- Defined in GHC.Base
infixr 0 $
Run Code Online (Sandbox Code Playgroud)

它说优先级:是5,而优先级$是0,这解释了为什么:绑定"比"更严格$.


Fre*_*Foo 6

:结合力强于$.考虑

Prelude> let f x = [x]
Prelude> 1 : f 2
[1,2]
Prelude> 1 : f $ 2

<interactive>:1:5:
    Couldn't match expected type `[a0]' with actual type `t0 -> [t0]'
    In the second argument of `(:)', namely `f'
    In the expression: 1 : f
    In the expression: 1 : f $ 2
Run Code Online (Sandbox Code Playgroud)

注意1 : f解析器找到的"表达式" ; 它看到(1 : f) $ 2而不是1 : (f $ 2).