Haskell:类型fa实际意味着什么?

For*_* O. 6 haskell functor

我偶然发现了fold ((,) <$> sum <*> product)带有类型签名的这段代码,:: (Foldable t, Num a) => t a -> (a, a)我完全迷失了.

我知道它的作用,但我不知道怎么做.所以我试着把它分成几小块:

?: :t (<$>)
(<$>) :: Functor f => (a -> b) -> f a -> f b
?: :t (,)
(,) :: a -> b -> (a, b)
?: :t sum
sum :: (Foldable t, Num a) => t a -> a
Run Code Online (Sandbox Code Playgroud)

一切都很好,只是基本的东西.

?: :t (,) <$> sum
(,) <$> sum :: (Foldable t, Num a) => t a -> b -> (a, b)
Run Code Online (Sandbox Code Playgroud)

而我又迷失了......

我看到有一些神奇的事情变成t a -> af a但是如何完成它对我来说是个谜.(sum甚至不是Functor!)

我一直认为这f a是一种f包含a但看起来意义更深的盒子.

Thr*_*eFx 5

f您的示例中的仿函数是所谓的"阅读器仿函数",其定义如下:

newtype Reader r = Reader (r -> a)
Run Code Online (Sandbox Code Playgroud)

当然,在Haskell中,这是为函数本地实现的,因此在运行时没有包装或解包.

相应的FunctorApplicative实例看起来像这样:

instance Functor f where
  fmap :: (a -> b) -> (r -> a)_-> (r -> b)
  fmap f g = \x -> f (g x) -- or: fmap = (.)

instance Applicative f where
  pure :: a -> (r -> a) -- or: a -> r -> a
  pure x = \y -> x -- or: pure = const
  (<*>) :: (r -> a -> b) -> (r -> a) -> (r -> b)
  frab <*> fra = \r -> frab r (fra r)   
Run Code Online (Sandbox Code Playgroud)

在某种程度上,读者仿函数也是一个"盒子",就像所有其他仿函数一样,具有r产生类型的上下文a.

那么让我们来看看(,) <$> sum:

:t (,) :: a -> b -> (a, b)
:t fmap :: (d -> e) -> (c -> d) -> (c -> e)
:t sum :: Foldable t, Num f => t f -> f
Run Code Online (Sandbox Code Playgroud)

我们现在可以将d类型专门设置为a ~ f,eto b -> (a, b)cto t f.现在我们得到:

:t (<$>) -- spcialized for your case
:: Foldable t, Num f => (a -> (b -> (a, b))) -> (t f -> f) -> (t f -> (b -> (a, b)))
:: Foldable t, Num f => (f -> b -> (f, b)) -> (t f -> f) -> (t f -> b -> (f, b))
Run Code Online (Sandbox Code Playgroud)

应用功能:

:t (,) <$> sum
:: Foldable t, Num f => (t f -> b -> (f, b))
Run Code Online (Sandbox Code Playgroud)

这正是ghc所说的.