给我解释一下

Eri*_*rik 10 haskell pointfree

潜入Haskell,当我享受这种语言时,我发现无点的风格完全难以辨认.我来过这个函数,它只包含这些ASCII鲣鸟,如下所示.

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

虽然我理解它的类型签名及其作用,但我无法理解为什么它会这样做.那么有人可以为我写出它的de-pointfreed版本,并且可能一步一步地回到无点版本sorta,如下所示:

f g x y = (g x) + y   
f g x = (+) (g x)    
f g = (+) . g    
f = (.) (+)
Run Code Online (Sandbox Code Playgroud)

sep*_*p2k 18

通常(?)(?代表任意中缀运算符)与...相同\x y -> x ? y.所以我们可以重写f为:

f = (\a b -> a . b) (\c d -> c . d)
Run Code Online (Sandbox Code Playgroud)

现在,如果我们将参数应用于函数,我们得到:

f = (\b -> (\c d -> c . d) . b)
Run Code Online (Sandbox Code Playgroud)

现在b只是一个参数f,所以我们可以将其重写为:

f b = (\c d -> c . d) . b
Run Code Online (Sandbox Code Playgroud)

定义.f . g = \x -> f (g x).如果.用其定义替换外部,我们得到:

f b = \x -> (\c d -> c . d) (b x)
Run Code Online (Sandbox Code Playgroud)

我们再次可以x变成一个常规参数:

f b x = (\c d -> c . d) (b x)
Run Code Online (Sandbox Code Playgroud)

现在让我们替换另一个.:

f b x = (\c d y -> c (d y)) (b x)
Run Code Online (Sandbox Code Playgroud)

现在让我们应用这个论点:

f b x = \d y -> (b x) (d y)
Run Code Online (Sandbox Code Playgroud)

现在让我们再次移动参数:

f b x d y = (b x) (d y)
Run Code Online (Sandbox Code Playgroud)

完成.

  • @Erik`\ab - > ...`是`\ a - >(\ b - > ...)`的缩写.所以你有一个函数,当给出一个参数`a`时,产生另一个期望参数`b`的函数.所以`a`是第一位的.或者换句话说:给出`(\ ab - > ...)1 2`,`a`将是`1`而`b`将是'2`.所以最左边的参数转到最左边的参数. (2认同)

Wil*_*ess 5

我们可以通过对组合子的定义进行“模式匹配”来反向工作。给定的

f a b c d =  a b  (c d) 
          = (a b) (c d)
Run Code Online (Sandbox Code Playgroud)

我们继续

         = B (a b) c d 
         = B B a b c d    -- writing B for (.)
Run Code Online (Sandbox Code Playgroud)

所以通过eta 收缩

f = B B 
Run Code Online (Sandbox Code Playgroud)

因为

a (b c) = B a b c         -- bidirectional equation
Run Code Online (Sandbox Code Playgroud)

根据定义。Haskell(.)实际上是B组合器(请参阅BCKW 组合器)。


编辑:潜在地,许多组合器可以匹配相同的代码。这就是为什么同一段代码有许多可能的组合编码。例如,(ab)(cd) = (ab)(I(cd))是有效的转换,这可能会导致其他一些组合子定义匹配的是。选择“最合适的”是一门艺术(或在具有较高分支因子的搜索空间中进行搜索)。

这是关于倒退,正如你所问的。但是,如果你想“向前”,我个人更喜欢组合方法,而不是 lambda 符号的烦躁。我什至会马上写很多参数,最后去掉多余的:

BBabcdefg = B(ab)cdefg = (ab)(cd)efg 
Run Code Online (Sandbox Code Playgroud)

因此,

BBabcd    = B(ab)cd    = (ab)(cd) 
Run Code Online (Sandbox Code Playgroud)

这就是全部。


Fre*_*ler 5

您还可以逐渐将参数附加到f

f = ((.) . )
f x = (.) . x
f x y = ((.) . x) y
      = (.) (x y)
      = ((x y) . )
f x y z = (x y) . z
f x y z t = ((x y) . z) t
          = (x y) (z t)
          = x y (z t)
          = x y $ z t
Run Code Online (Sandbox Code Playgroud)

结果表明xz实际上是(分别为二进制和一元)函数,因此我将使用不同的标识符:

f g x h y = g x (h y)
Run Code Online (Sandbox Code Playgroud)