我偶然发现了这段代码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 中,这是为函数原生实现的,因此在运行时没有包装或解包。
对应的
Functor
和 Applicative
实例如下所示: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
, e
至b -> (a, b)
和 c
至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))
应用功能:
:t (,) <$> sum
:: Foldable t, Num f => (t f -> b -> (f, b))
这正是 ghc 所说的。
关于Haskell:类型 f a 实际上是什么意思?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40291206/