Haskell:类型 f a 实际上是什么意思?

标签 haskell functor

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

我知道它做了什么,但我不知道怎么做。所以我试图在 ghci 中把它分解成小块:

λ: :t (<$>)
(<$>) :: Functor f => (a -> b) -> f a -> f b
λ: :t (,)
(,) :: a -> b -> (a, b)
λ: :t sum
sum :: (Foldable t, Num a) => t a -> a

一切都很好,只是基本的东西。
λ: :t (,) <$> sum
(,) <$> sum :: (Foldable t, Num a) => t a -> b -> (a, b)

而我又迷路了……

我看到发生了一些神奇的事情,变成了 t a -> a进入 f a但它是如何完成的对我来说是个谜。 ( sum 甚至不是 Functor 的实例!)

我一直以为f a是某种盒子f包含 a但看起来意义要深得多。

最佳答案

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

newtype Reader r = Reader (r -> a)

当然,在 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)   

在某种程度上,阅读器仿函数也是一个“盒子”,就像所有其他仿函数一样,有一个上下文 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

我们现在可以专门化 d输入 a ~ f , eb -> (a, b)ct 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))

应用功能:
:t (,) <$> sum
:: Foldable t, Num f => (t f -> b -> (f, b))

这正是 ghc 所说的。

关于Haskell:类型 f a 实际上是什么意思?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40291206/

相关文章:

haskell - forkIO/forkOS 和 forkProcess 之间的区别?

haskell - ReaderT Monad Transformer 中 * 的用途是什么?

c++ - 在 C++ 中,编译器将函数对象设为 "inline"意味着什么?

haskell - Either a 和 Either Int 有什么区别?什么是要么 a ?多态类型构造函数?它的目的是什么?

Haskell 中的嵌套空列表列表

haskell - 特殊括号 (| ... |) 脱糖成什么?

haskell - 任意多个不同类型列表的笛卡尔积

scala - 如何简化嵌套 map 调用?

Haskell:hackage Control.Applicative 文章中应用仿函数定律的描述中的缺陷?:它说 Applicative 决定 Functor

c++ - 如何将仿函数用作类模板中的成员?