2013-07-12 51 views
7

haskell.org我碰到这点自由风格的函数来了(()$())(==)的含义,被称为 “猫头鹰”。有人可以解释1(1+)0

((.)$(.)) 

它的类型签名是 (a -> b -> c) -> a -> (a1 -> b) -> a1 -> c

这相当于 f a b c d = a b (c d) 显然, ((.)$(.)) (==) 1 (1+) 0 回报True

所以我的问题是:

  1. 是什么在类型签名a1是什么意思?它与a有关吗?
  2. (==)某种功能相等运算符的?因为0 (==) 0在GHCi中引发错误。
  3. 1 (1+) 0这是什么意思?我不明白这是甚么有效的表达。
  4. 为什么表达式返回True
+2

请注意'((。)$(。))'中的'$'是不必要的;表达式'((。)(。))'是完全等价的。 –

回答

15
  1. a1 “只是另一种类型的变量”。这可能意味着什么,包括a,但不一定意味着什么。最有可能与a不同。

  2. (==)==的“强制前缀”形式,常规等于运算符构成Eq类型的类。通常你会写a == b,但这仅仅是(==) a b的语法糖,其前缀应用为==

  3. 1 (1+) 0在这种情况下并不意味着什么,三个子表达式中的每一个都是对“猫头鹰”的独立论证,最终有四个论点。

  4. 我们可以通过减少行走。

    ((.)$(.)) (==) 1 (1+) 0 
    ===       [ apply ] 
    ((.)(.)) (==) 1 (1+) 0 
    ===       [ implicit association ] 
    ((.)(.)(==)) 1 (1+) 0 
    ===       [ apply the definition: (f.g) x = f (g x) ] 
    ((.) (1 ==)) (1+) 0 
    ===       [ implicit association ] 
    ((.) (1 ==) (1+)) 0 
    ===       [ apply the definition: (f.g) x = f (g x) ] 
    1 == (1+0) 
    ===       [addition] 
    1 == 1 
    ===       [equality] 
    True 
    

由于this page提到,猫头鹰就相当于一个功能f

f a b c d = a b (c d) 

这就是说它适用其第一个参数的两个参数的函数,其第二个论点和将第三个论点应用于第四个论证的结果。对于这意味着你首先应用(+1)0给出((.)$(.)) (==) 1 (1+) 0的例子,然后再结合1和使用(==)这是我们减少发生了什么(1+0)

更广泛地说,你可以把它作为修改二元运算a采取第二个参数稍有变化的功能。

+0

我明白了,我忘记了强制前缀。我认为这是正常意义上的括号。感谢您的评估演练 –

+2

Nit:'(==)1'是'(1 ==)',而不是'(== 1)'。不是说它对'=='的默认定义很重要,但... –

+0

好点!固定。 –

0

首先,我们写_B f g x = f (g x) = (f . g) x

由于f $ x = f x,我们有(.)$(.) = _B $ _B = _B _B。其类型被机械地衍生,如

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

1. (.) :: (b1 -> c1) -> ((a1 -> b1) -> (a1 -> c1)) 

2. (.) (.) :: {b ~ b1 -> c1, c ~ (a1 -> b1) -> (a1 -> c1)} (a -> b) -> (a -> c) 

      :: (a -> b1 -> c1) -> a -> (a1 -> b1) -> (a1 -> c1) 
      :: (a -> b -> c) -> a -> (a1 -> b) -> a1 -> c 

aa1是两个不同类型的变量,就像bb1。但由于最终类型中没有bc,我们可以将b1c1重新命名为bc,以简化。但不是a1

实际上我们可以读到这个类型:它获得了一个二元函数f :: a -> b -> c; x :: a参数值,g :: a1 -> b一元函数,和另一个值y :: a1,并结合他们唯一可能的方式,这样的类型适合:

f x  :: b -> c 
    g y  :: b 
    f x (g y) ::  c 

其余部分已经回答。通常在组合方程式中可以很容易地使用简化方法,例如_B _B f x g y = _B (f x) g y = f x (g y),只需要两个应用_B的定义(我们可以随时添加尽可能多的参数)。