表达式的评估str a b =((。)。(。))(0 - )(+)1 2

时间:2013-08-30 10:30:08

标签: haskell pointfree

您能解释一下以下表达式的工作原理:

str a b = ((.).(.)) (0 -) (+) 1 2

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

我还检查了以下内容:

*Main> :t ((.).(.))
((.).(.)) :: (b -> c) -> (a -> a1 -> b) -> a -> a1 -> c

但它没有帮助我。

有什么想法吗?

3 个答案:

答案 0 :(得分:9)

运算符(.).(.)有时会被赋予别名:

(.:) = (.).(.)

您可以将其视为(.),只有在第二个函数接受两个参数时才有效。所以这有用,例如:

sqrtsum = sqrt .: (+)
-- sqrtsum 4 5 ==> 3.0

这将取两个数字,求它们然后取总和的平方根。 .:别名有点视觉,你可以想象冒号表示两个参数的函数连接到一个参数的函数。

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

(.) :: (b -> c) -> (a -> b) -> (a -> c)

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

(.:) :: (b -> c) -> (a1 -> a2 -> b) -> (a1 -> a2 -> c)

它的作用是它需要一个函数a1 -> a2 -> b和一个函数b -> c,它会为您提供一个直接从a1a2到{{ 1}}。

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

(.)

在表达式

(.) :: (b -> c) -> (a -> b) -> (a -> c)

也可以写成

(.).(.)

(.) (.) (.) (.)a -> b)的两个参数函数本身都是b -> c - 所以你可以替换很多(.)ab以及它们真正代表的内容!

答案 1 :(得分:8)

如果您手动扩展lambda术语,您将学到最多。或者,如果您懒惰,请使用tool

无论如何,这是:

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

答案 2 :(得分: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,其值为{{1}并且整个函数返回c因此-3是最终答案。