【问题标题】:Is (fmap f) the same as (f .) if f is a function of type a->b?如果 f 是 a->b 类型的函数, (fmap f) 是否与 (f .) 相同?
【发布时间】:2019-08-29 01:08:20
【问题描述】:

我正在尝试实现

的 Functor 实例
data ComplicatedA a b
    = Con1 a b
    | Con2 [Maybe (a -> b)]

对于 Con2,我的想法是 fmap 需要类似于

fmap f (Con2 xs) = Con2 (map f' xs)

那么我需要一个列表映射函数 f' 像

Maybe (a -> x) -> Maybe (a -> y)

由于Maybe是一个Functor,我可以写成f'这样的

fmap ((a->x) -> (a->y))

为了得到((a->x) -> (a->y)),我以为我可以做到 fmap (x->y)(fmap f) 相同

所以我的建议是

instance Functor (ComplicatedA a) where
    fmap f (Con1 x y) = Con1 x (f y)
    fmap f (Con2 xs) = Con2 (map (fmap (fmap f)) xs)

然而真正的解决方案是使用(f .) 而不是(fmap f)x -> y 获取((a->x) -> (a->y)),它看起来像这样

instance Functor (ComplicatedA a) where
    fmap f (Con1 a b) = Con1 a (f b)
    fmap f (Con2 l) = Con2 (map (fmap (f .)) l)

我只是想知道我的思考过程和解决方案有什么问题。如果 f 是 a->b 类型的函数, (fmap f) 是否与 (f .) 相同?

提前谢谢你。

【问题讨论】:

  • fmap f 确实与(f .) 相同,如果所讨论的函子是函数(通常表示为(->) r)。
  • @RobinZigmond 谢谢。那么我的解决方案也正确吗?
  • 我相信是的。 (但我不是专家,现在没有时间详细检查。)
  • ...您甚至可以将map 替换为fmap,使其阅读起来更有趣。 fmap f (Con2 l) = Con2 (fmap (fmap (fmap f)) l)。然后决定用更多fmaps 会更有趣,fmap (fmap (fmap f))fmap . fmap . fmap $ f(.)fmap,所以Con2 (fmap fmap (fmap fmap fmap) f l)
  • @klabe 在我看来,您的解决方案不仅是正确的,而且比另一个更具可读性。你基本上需要通过两个函子a ->Maybe“提升”f :: b->b',所以使用两个fmaps 对我来说感觉很自然。我也想要fmap (fmap (fmap f)),因为[] 是第三个函子。 (当然,最简单的就是写deriving Functor,让GHC为我们做,但是手工写functor实例对于学习functor是如何工作的很有用)

标签: haskell functor


【解决方案1】:

解决方案确实是等价的。 fmap for the function/reader functor(.)

instance Functor ((->) r) where
    fmap = (.)

(->) r 是使用前缀语法的函数类型构造函数 -- (->) r ar -> a 相同。)

直觉是,正如您所指出的,(.) :: (x -> y) -> (a -> x) -> (a -> y) 使用x -> y 函数来修改a -> x 函数的结果。

【讨论】:

  • 我希望语法 (r ->) 被允许,因为我看到人们将 (->) r 误读为函数 to r 而不是 from i> - 麻烦的是,它建议(-> r) 将被允许,但它不能,因为它会影响更高种类的统一的可判定性。呜呜呜。
  • 那确实很有帮助,@JonPurdy
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-27
  • 2018-11-10
  • 1970-01-01
  • 2019-12-19
  • 2020-12-25
  • 2022-11-10
相关资源
最近更新 更多