表达式的评估str ab =((.).(.))(0 - )(+)1 2

Jos*_*rad 4 haskell pointfree

你能解释一下下面的表达式是如何工作的:

str a b = ((.).(.)) (0 -) (+) 1 2
Run Code Online (Sandbox Code Playgroud)

我检查了它,GHCi说它是,-3但我不明白为什么.

我还检查了以下内容:

*Main> :t ((.).(.))
((.).(.)) :: (b -> c) -> (a -> a1 -> b) -> a -> a1 -> c
Run Code Online (Sandbox Code Playgroud)

但它对我没有帮助.

任何的想法?

kqr*_*kqr 9

(.).(.)有时给运营商一个别名:

(.:) = (.).(.)
Run Code Online (Sandbox Code Playgroud)

你可以查看它(.),只有当第二个函数有两个参数时它才有效.所以这有用,例如:

sqrtsum = sqrt .: (+)
-- sqrtsum 4 5 ==> 3.0
Run Code Online (Sandbox Code Playgroud)

这将取两个数字,求和,然后取总和的平方根.该.:别名排序使得视觉感,你可以想像表示两个参数的函数结肠被连接到一个参数的函数.

如果您愿意,可以查看(.)类似的类型签名:

(.) :: (b -> c) -> (a -> b) -> (a -> c)
Run Code Online (Sandbox Code Playgroud)

这意味着它(.)需要两个函数a -> b并将b -> c它们"连接在一起"并a直接返回一个函数c.运算符的(.:)工作方式类似 - 您可以将其类型签名写为

(.:) :: (b -> c) -> (a1 -> a2 -> b) -> (a1 -> a2 -> c)
Run Code Online (Sandbox Code Playgroud)

它的作用是它需要一个函数a1 -> a2 -> b和一个函数b -> c,它会为你提供一个直接从a1a2到达的函数c.

如果您想亲自验证此类型,您可以(.:)使用签名进行操作(.).我不会为你做这件事,部分是因为它可能最终成为一个文本墙,部分原因是因为你在推理代码时对你来说是一个很好的练习!如果你需要一个地方开始,请记住

(.) :: (b -> c) -> (a -> b) -> (a -> c)
Run Code Online (Sandbox Code Playgroud)

在表达中

(.).(.)
Run Code Online (Sandbox Code Playgroud)

也可以写成

(.) (.) (.)
Run Code Online (Sandbox Code Playgroud)

(.)(a -> bb -> c)的两个参数函数都是它们(.)自己 - 所以你可以用它们真正代表的东西替换很多as和bs和cs!


phi*_*ler 8

如果您手动扩展lambda术语,您将学到最多.或者,如果你很懒,请使用工具.

无论如何,这里是:

dot = ?f.?g.?x.f (g x)

dot dot dot (0 -) + 1 2
?   (?g.?x.dot (g x)) dot (0 -) + 1 2
?   (?x.dot (dot x)) (0 -) + 1 2
?   dot (dot (0 -)) + 1 2
?   (?g.?x.dot (0 -) (g x)) + 1 2
?   (?x.dot (0 -) (+ x)) 1 2
?   dot (0 -) (+ 1) 2
?   (?g.?x.0 - (g x)) (+ 1) 2
?   (?x.0 - (+ 1 x)) 2
?   0 - (+ 1 2)
?   0 - 3
Run Code Online (Sandbox Code Playgroud)


Ank*_*kur 7

类型: (b -> c) -> (a -> a1 -> b) -> a -> a1 -> c

价值观: (0 -)_______(+)_______________1___2

1是a,2是a1,(+)(a -> a1 -> b)..适用(+)于1和2你得到3现在是值b.

(0 -)(b -> c),将3(在b上面)应用于此,你将获得(0-3),即-3它的值是,c并且整个函数返回,c因此-3是最终答案.