组成更高的功能

pio*_*rek 10 haskell functional-programming higher-order-functions

我不明白使用arity> 1编写函数.在ghci 7.4.1我输入:

((*).succ) 3 4
> 16
Run Code Online (Sandbox Code Playgroud)

我并不完全理解数学变换,但很明显它与数学变换相同

(*) (succ 3) 4
Run Code Online (Sandbox Code Playgroud)

但当我这样做时:

( (\x y z -> x).(\a b -> a*b) ) 2 3 4 5
> 10
( (\x y z -> y).(\a b -> a*b) ) 2 3 4 5
> No instance for (Num (a0 -> t0))
Run Code Online (Sandbox Code Playgroud)

现在我完全迷失了.有人能解释会发生什么吗?PS.我知道haskell中的所有内容只有1个参数,但它并没有真正帮助我:)

JB.*_*JB. 12

以这种方式解决:

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

然后将f替换为f (*),使用succx和y 代替它们的值:

((*) . succ) 3 4 = (*) (succ 3) 4
                 = (*) 4 4
                 = 16
Run Code Online (Sandbox Code Playgroud)


Nik*_*kov 5

撰写时,(\x y z -> x) . (\a b -> a*b)您将撰写以下签名的功能:

(\x y z -> x) :: a -> b -> c -> a
(\a b -> a*b) :: Num a => a -> a -> a
Run Code Online (Sandbox Code Playgroud)

签名(.)

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

现在,让我们把事情放在一起,以获得(.)这些功能的特殊签名版本.

  1. 首先,我们将签名(b -> c)部分专门化为:(.)a -> b -> c -> a

    (b -> (z -> x -> b)) -> (a -> b) -> a -> (z -> x -> b)
    
    Run Code Online (Sandbox Code Playgroud)

    得到它?该c(z -> x -> b).

  2. 现在让我们(a -> b)(.)签名部分专门化为a -> a -> a:

    ((a -> a) -> (z -> x -> (a -> a))) -> (a -> (a -> a)) -> a -> (z -> x -> (a -> a))
    
    Run Code Online (Sandbox Code Playgroud)

    b(a -> a).

  3. 现在让我们删除多余的括号:

    ((a -> a) -> z -> x -> a -> a) -> (a -> a -> a) -> a -> z -> x -> a -> a
    
    Run Code Online (Sandbox Code Playgroud)
  4. 现在这里是一个来自ghci的会话,显示签名如何更改,同时我将所有参数应用于该签名的函数:

    > let f = undefined :: ((a -> a) -> z -> x -> a -> a) -> (a -> a -> a) -> a -> z -> x -> a -> a
    > :t f (\x y z -> x)
    f (\x y z -> x) :: (a -> a -> a) -> a -> z -> x -> a -> a
    > :t f (\x y z -> x) (\a b -> a*b)
    f (\x y z -> x) (\a b -> a*b) :: Num a => a -> z -> x -> a -> a
    > :t f (\x y z -> x) (\a b -> a*b) 2
    f (\x y z -> x) (\a b -> a*b) 2 :: Num a => z -> x -> a -> a
    > :t f (\x y z -> x) (\a b -> a*b) 2 3
    f (\x y z -> x) (\a b -> a*b) 2 3 :: Num a => x -> a -> a
    > :t f (\x y z -> x) (\a b -> a*b) 2 3 4
    f (\x y z -> x) (\a b -> a*b) 2 3 4 :: Num a => a -> a
    > :t f (\x y z -> x) (\a b -> a*b) 2 3 4 5
    f (\x y z -> x) (\a b -> a*b) 2 3 4 5 :: Num a => a    
    
    Run Code Online (Sandbox Code Playgroud)

以上解释了如何( (\x y z -> x).(\a b -> a*b) ) 2 3 4 5工作.

现在这里是如何( (\x y z -> y).(\a b -> a*b) ) 2 3 4 5翻译:

((a -> a) -> z -> x -> z) -> (a -> a -> a) -> a -> z -> x -> z
Run Code Online (Sandbox Code Playgroud)

以下是会议结果:

> let f = undefined :: ((a -> a) -> z -> x -> z) -> (a -> a -> a) -> a -> z -> x -> z
> :t f (\x y z -> x)
f (\x y z -> x) :: (a -> a -> a) -> a -> (a -> a) -> x -> a -> a
> :t f (\x y z -> x) (\a b -> a*b)
f (\x y z -> x) (\a b -> a*b)
  :: Num a => a -> (a -> a) -> x -> a -> a
> :t f (\x y z -> x) (\a b -> a*b) 2
f (\x y z -> x) (\a b -> a*b) 2 :: Num a => (a -> a) -> x -> a -> a
> :t f (\x y z -> x) (\a b -> a*b) 2 3
f (\x y z -> x) (\a b -> a*b) 2 3
  :: (Num a, Num (a -> a)) => x -> a -> a
Run Code Online (Sandbox Code Playgroud)

最后一行解释了您的错误消息.显然不可能有任何Num实例a -> a.