我们知道fmap
是fmap :: Functor f => (a -> b) -> f a -> f b
和sum
是sum :: (Num a, Foldable t) => t a -> a
,但下面的代码混淆了我。为什么`fmap sum just` typecheck?
> :t (fmap sum Just)
(fmap sum Just) :: Num b => b -> b
> fmap sum Just 3
3
为什么?
我们知道fmap
是fmap :: Functor f => (a -> b) -> f a -> f b
和sum
是sum :: (Num a, Foldable t) => t a -> a
,但下面的代码混淆了我。为什么`fmap sum just` typecheck?
> :t (fmap sum Just)
(fmap sum Just) :: Num b => b -> b
> fmap sum Just 3
3
为什么?
我想这里可能有两个令人困惑的位。
首先,最明显的是,sum
适用于Foldable
的东西,而不仅仅是列表。因此:
sum (Just 3) == 3
第二个是您正在使用的仿函数实例。由于Just
是一个函数,因为这是fmap
的第二个参数,因此您正在使用fmap的读取器实例,此处将(https://hackage.haskell.org/package/base-4.9.1.0/docs/src/GHC.Base.html#line-638)定义为(.)
。
它看起来怪异,喜欢它应该不是类型检查,因为你提供三个参数FMAP,但实际上,在(FMAP只是总和)的结果是一个函数:
Prelude> :t fmap sum Just
fmap sum Just :: Num b => b -> b
如果我们用.
代替fmap
,事情开始变得更有意义了。
Prelude> (.) sum Just 3
3
Prelude> (sum . Just) 3
3
这是一样的
sum (Just 3)
非常感谢。我是haskell新手。我还没有学过读者实例,但我认为你是对的。我会在稍后检查。 –
不客气。这个实例在大多数情况下通常显示为'(( - >)r)',当它出现在某个地方时,很容易就会错过发生了什么,因为函数觉得它们应该有某种特殊的行为,但是在Haskell中像所有其他类型的类型,因此它比其他语言更加一致。 –
我敢肯定,你可以尝试[它](https://www.tryhaskell.org/)。 –
是的,我意识到'sum'来自'Data.Foldable' – zerkms