代码之家  ›  专栏  ›  技术社区  ›  geckos

为什么即使我没有应用f参数,我也需要再次调用构造函数来获取fmap?

  •  1
  • geckos  · 技术社区  · 3 年前

    我不知道为什么 fmap _ a = a 下面是非法的。以下是代码:

    data Sum a b = First a | Second b
    
    instance Functor (Sum a) where
      fmap f (Second b) = Second (f b)
      fmap _ (First a)  = First a
      fmap _ a          = a  -- Why can't I do this instead?
    

    另一个问题是,这是否会影响性能,还是只会在编译时发生?

    0 回复  |  直到 3 年前
        1
  •  3
  •   dfeuer    3 年前

    关于性能:在编译过程的后期,当GHC擦除了大多数类型信息时,它会尽最大努力注意何时正在像这样重建值。这一步可以捕捉到很多情况,但不是全部;有时,代码的转换方式会使重建不再明显。

        2
  •  2
  •   Will Ness Derri Leahy    3 年前

    你需要调用构造函数 重新 创建a 值,因此它的类型将与您开始使用的类型不同。

    fmap ::   (b -> c) ->    Sum a b  -> Sum a c
    fmap (f :: b -> c) ::    Sum a b  -> Sum a c
    fmap (f :: b -> c) (x :: Sum a b) -> Sum a c
    
                     a ::     a               a ::     a
               First a :: Sum a b       First a :: Sum a c
    
                     b ::       b             c ::       c
              Second b :: Sum a b      Second c :: Sum a c
    

    鉴于 a :: a , First a 具有类型 Sum a t 具有 t 由上下文决定 首先a 出现。两个 首先a 等号的两侧定义了两个不同的值,每个值都有自己的类型。使用变量 a 在右边,它仍然指的是类型的相同值 Sum a b 因为它在左边。但我们需要一种不同的类型,根据 fmap .

        3
  •  1
  •   David Fox    3 年前

    你不能这样做的原因是因为结果类型 fmap 取决于结果类型 f ,但是表达 a 没有。也就是说,你没有约束 f b ~ a .