试图了解最终签名是如何推断的:
GHCi> :t (+)
(+) :: Num a => a -> a -> a
GHCi> :t (<*>)
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
GHCi> :t (<*>) (+)
(<*>) (+) :: Num b => (b -> b) -> b -> b
(a' -> a' -> a')
必须与f (a -> b)
统一,因此f
可能属于((->) r)
类型:
(<*>) :: Applicative ((->) r) => r -> (a -> b) -> (r -> a) -> (r -> b)
(<*>) (+) ~ a' -> (a' -> a') -> (a' -> a') -> (a' -> a')
(<*>) (+) :: (a' -> a') -> (a' -> a') -- ^^^ got stuck here
有人可以解释如何获得最终类型吗?
感谢。
答案 0 :(得分:12)
您遇到的问题是->
的正确关联性。考虑<*>
:
<*> :: (Applicative f) => f (a -> b) -> f a -> f b
f a
等于r -> a
,我们有
<*> :: f (a -> b) -> f a -> f b
:: (r -> (a -> b)) -> (r -> a) -> (r -> b)
:: (r -> a -> b) -> (r -> a) -> (r -> b) -- This is the key line
请注意,它从(r -> (a -> b)) -> other stuff
转到(r -> a -> b) -> other stuff
,而不是r -> (a -> b) -> other stuff
。我们可以删除内括号,因为它们位于箭头的右侧,但我们无法删除外括号,因为它们位于箭头的左侧。
现在,(+) :: (Num a) => a -> a -> a
。当<*>
与r
相同而a
与b
相同时,这完全符合(<*>) (+) :: (Num a) => (a -> a) -> (a -> a)
:: (Num a) => (a -> a) -> a -> a
的第一个参数,它们都是数字。总之,我们得到了
{{1}}
再次注意我正在删除右边的括号,但不在箭头左侧。