我试图了解的结果
(*) . (+)
在Haskell。我知道合成运算符只是数学函数的标准合成-所以
(f . g) = f (g x)
但:
(*) . (+) :: (Num (a -> a), Num a) => a -> (a -> a) -> a -> a
我正在努力理解这种类型的签名。我本来希望能够做到:
((*) . (+)) 1 2 :: Num a => a -> a
= (* (+ 1 2))
是什么意思 (*) 。(+)的类型签名?我尝试通过类似的方式(仅与其签名匹配)来玩:
((*) . (+)) 1 (\x -> x + 1) 1
但这无法编译。在编写这些代码时,我试图通过逻辑步骤,但我还没有完全理解它如何达到此结果(以及结果是什么)。
我理解你的感受。我一开始也发现功能组成也很难掌握。使我困惑的是类型签名。考虑:
(*) :: Num x => x -> x -> x
(+) :: Num y => y -> y -> y
(.) :: (b -> c) -> (a -> b) -> a -> c
现在,当您编写时,(*) . (+)
它实际上与(.) (*) (+)
(即(*)
是的第一个参数(.)
,(+)
是的第二个参数(.)
)相同:
(.) :: (b -> c) -> (a -> b) -> a -> c
|______| |______|
| |
(*) (+)
因此,(*)
(即Num x => x -> x -> x
)的类型签名与b -> c
:
(*) :: Num x => x -> x -> x -- remember that `x -> x -> x`
| |____| -- is implicitly `x -> (x -> x)`
| |
b -> c
(.) (*) :: (a -> b) -> a -> c
| |
| |‾‾‾‾|
Num x => x x -> x
(.) (*) :: Num x => (a -> x) -> a -> x -> x
因此,(+)
(即Num y => y -> y -> y
)的类型签名与Num x => a -> x
:
(+) :: Num y => y -> y -> y -- remember that `y -> y -> y`
| |____| -- is implicitly `y -> (y -> y)`
| |
Num x => a -> x
(.) (*) (+) :: Num x => a -> x -> x
| | |
| |‾‾‾‾| |‾‾‾‾|
Num y => y y -> y y -> y
(.) (*) (+) :: (Num (y -> y), Num y) => y -> (y -> y) -> y -> y
我希望可以弄清“Num (y -> y)
和”的Num y
来源。您会留下一个非常奇怪的type函数(Num (y -> y), Num y) => y -> (y -> y) -> y -> y
。
是什么使得它如此奇怪的是,它希望既y
和y -> y
为实例Num
。可以理解y
应该是的实例,这是可以理解的Num
,但是怎么做y -> y
呢?制作y -> y
的实例Num
似乎不合逻辑。那是不正确的。
但是,当您查看实际的功能组合时,这才有意义:
( f . g ) = \z -> f ( g z)
((*) . (+)) = \z -> (*) ((+) z)
所以你有一个功能\z -> (*) ((+) z)
。因此,z
显然必须是Num
因为(+)
已应用了它的一个实例。这样的类型\z -> (*) ((+) z)
就是Num t => t -> ...
其中...
的类型(*) ((+) z)
,我们将在稍后发现。
因此((+) z)
属于这种类型,Num t => t -> t
因为它需要再加上一个数字。但是,在将其应用于另一个数字之前,(*)
已对其应用。
因此(*)
期望((+) z)
是的实例Num
,这就是为什么t -> t
期望是的实例Num
。因此,...
替换为,(t -> t) -> t -> t
并Num (t -> t)
添加了约束,从而产生了type (Num (t -> t), Num t) => t -> (t -> t) -> t -> t
。
你真的想结合的方式(*)
,并(+)
为使用(.:)
:
(.:) :: (c -> d) -> (a -> b -> c) -> a -> b -> d
f .: g = \x y -> f (g x y)
因此(*) .: (+)
与相同\x y -> (*) ((+) x y)
。现在有两个论点可以(+)
确保((+) x y)
确实是正义的Num t => t
和不正义的Num t => t -> t
。
因此((*) .: (+)) 2 3 5
,(*) ((+) 2 3) 5
哪个是(*) 5 5
哪个25
,我相信这就是您想要的。
请注意,f .: g
也可以写成(f .) . g
,(.:)
也可以定义成(.:) = (.) . (.)
。你可以在这里读更多关于它的内容:
希望能有所帮助。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句