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)
撰写时,(\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)
现在,让我们把事情放在一起,以获得(.)这些功能的特殊签名版本.
首先,我们将签名(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).
现在让我们(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).
现在让我们删除多余的括号:
((a -> a) -> z -> x -> a -> a) -> (a -> a -> a) -> a -> z -> x -> a -> a
Run Code Online (Sandbox Code Playgroud)现在这里是一个来自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.