【发布时间】:2020-02-20 22:36:29
【问题描述】:
我正在阅读“Haskell 编程”一书(第二版),偶然发现了练习 2,第 12 章,第 2 部分:
instance Functor ((->) a) where
fmap = TODO
答案在哪里:
instance Functor ((->) a) where
fmap = (.)
这让我摸不着头脑。我想这在直观层面上对我来说确实有意义(部分应用函数类型 a -> 是函子,而组合是它的 fmap),但我认为一些很好的例子会巩固我对练习的理解。
我想出了这两个:
main = do
putStrLn . show $ (fmap (+1) (*2)) (5 :: Int)
putStrLn . show $ (fmap (show) (+1)) 3
我的例子是否正确地说明了这个练习?
fmap 给定两个参数:
- 部分应用函数(函数)
- 另一个部分应用的函数(函子)
更新
fmap 给出两个参数:
- 函数(函数)
- 另一个函数(函子)
对我来说只是看起来很奇怪,我不确定我的概念是否正确。
我在 SO 上看到了一些类似的问题(例如 this one),其中 this one 几乎是我正在寻找的东西,但并不完全是(我只是在寻找函子的例子,没有别的 - 没有应用程序和没有单子)。
【问题讨论】:
-
基本上
fmap f g会将g的结果与f进行“后处理”。 -
这两个参数是 not 本身 部分应用 函数。这些只是函数。
-
@WillemVanOnsem 谢谢。对,这些是功能。我想让我感到困惑的是
Functor类所需的类型参数的数量。看起来Functor只需要来自其实例的一个参数,而(->)类型需要两个参数。为了解决这个问题,必须部分应用(->),以便只需要一个参数。我的理解正确吗? -
@PiotrJustyna 是的,这是完全正确的——(更高种类的)类型可以以与函数完全相同的方式部分应用。 [任一] 是部分应用类型构造函数的另一个很好的例子,它形成了
Functor(实际上也是Applicative和Monad)。 -
请注意,有 个类似函子的东西可以作用于类型为
Type -> Type -> Type的类型。例如,双函子允许您映射两种不同类型的值。通常的例子是(,):bimap f g (x, y) == (f x, g y),其中(,) a的函子实例只允许您将函数映射到第二个元素(fmap f (x,y) == (x, f y))。还有一些profunctors,有点奇怪,虽然(->)实例比较容易理解,如果很少使用:dimap f g h == g . h . f。