关于Haskell函数组合的困惑

关于Haskell函数组合的困惑,haskell,function-composition,pointfree,Haskell,Function Composition,Pointfree,考虑ghci中的以下函数定义 let myF = sin . cos . sum 何处。表示两个函数的组合(右关联)。这个我可以打电话 myF [3.14, 3.14] 它给了我想要的结果。显然,它将list[3.14,3.14]传递给函数“sum”,并将其“result”传递给cos等等。但是,如果我在解释器中这样做 let myF y = sin . cos . sum y 或 然后我遇到了麻烦。将此修改为以下内容可以得到所需的结果 let myF y = sin . cos $

考虑ghci中的以下函数定义

let myF = sin . cos . sum 
何处。表示两个函数的组合(右关联)。这个我可以打电话

myF [3.14, 3.14]
它给了我想要的结果。显然,它将list[3.14,3.14]传递给函数“sum”,并将其“result”传递给cos等等。但是,如果我在解释器中这样做

let myF y = sin . cos . sum y 

然后我遇到了麻烦。将此修改为以下内容可以得到所需的结果

let myF y = sin . cos $ sum y 

(.)的类型表明,以下形式不应该有问题,因为“sum y”也是一个函数(不是吗?毕竟在Haskell中,一切都是函数?)

更有趣的是,我可以使用两个(或多个)参数(将传递列表[3.14,3.14]想象为两个参数x和y),我必须编写以下内容

let (myF x) y = (sin . cos . (+ x)) y 
myF 3.14 3.14 -- it works! 
let myF = sin . cos . (+) 
myF 3.14 3.14 -- -- Doesn't work!

HaskellWiki上有一些关于这种形式的讨论,他们称之为“无点”形式。通过阅读本文,我怀疑这种形式不同于两个lambda表达式的组合。当我试图画一条线来区分这两种风格时,我感到困惑。

不,
求和y
不是一个函数。这是一个数字,就像
sum[1,2,3]
is一样。因此,完全可以理解的是,您不能将函数组合运算符
(.)
与它一起使用

并非Haskell中的所有内容都是函数

让我们看一看。对于
sin
cos
我们有:

cos, sin :: Floating a => a -> a
对于
总和

sum :: Num a => [a] -> a
现在,
sum y
将其转换为

sum y :: Num a => a
这是一个值,而不是一个函数(你可以把它命名为一个没有参数的函数,但这是非常棘手的,你还需要命名
()->a
函数-在某个地方对此进行了讨论,但我现在找不到链接-谈到了它)

不管怎样,试着去做。sum y不起作用,因为
希望双方都有类型
a->b
b->c
(签名是
(b->c)->(a->b)->(a->c)
),并且
sum y
不能用这种样式编写。这就是为什么需要包含括号或
$

对于无点风格,simples的翻译方法如下:

  • 使用函数并将函数的最后一个参数移动到由函数应用程序分隔的表达式末尾。例如,在
    mysum x y=x+y
    的情况下,我们在末尾有
    y
    ,但我们现在无法删除它。相反,重写为
    mysumxy=(x+y
    是可行的
  • 删除上述论点。在我们的例子中,
    mysum x=(x+)
  • 重复,直到你没有更多的论点。这里
    mysum=(+)

(我选择了一个简单的例子,对于更复杂的情况,你必须使用
翻转
和其他方法)

强制性的神秘答案是:
(空格)比
绑定得更紧

Haskell中的大多数空格可以被认为是一个非常高的固定性
$
(“apply”函数)<代码>wx。y z
(w$x)基本相同。(y$z)


当你第一次学习
$
时,你还应该确保你也学习了
(空格),并且确保你理解了语言语义是如何以一种可能(乍一看)不直观的方式隐式插入事物的。

嗨,Mihai。谢谢你。如果你能找到链接,请让我知道。提前感谢。让这一点更清楚的是查看
的类型,即
(b->c)->(a->b)->(a->c)
。更新了
的链接和签名,如@Antal S-Z suggestedIt不是真的“一切都是Haskell中的函数”康纳尔·埃利奥特(Conal Elliot)说过。我以为数字是带有无效参数的函数。@eternalmatt:阅读上面评论中链接到的博客文章Antal S-Z。
cos, sin :: Floating a => a -> a
sum :: Num a => [a] -> a
sum y :: Num a => a