为什么即使我不应用 f 参数,我也需要在 fmap 的定义中再次调用构造函数?

问题描述

我不知道为什么下面的 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?

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

解决方法

关于性能:在编译过程的后期,当 GHC 删除了大部分类型信息时,最好注意何时像这样重构值。这一步捕获了很多情况,但不是全部;有时代码会以这样的方式进行转换,以至于重构不再明显。

,

您需要调用构造函数 anew 来创建一个 new 值,因此它的类型将与您开始使用的类型不同。

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 :: aFirst a 的类型为 Sum a t,其中 tFirst a 出现的上下文决定。等号两边的两个 First a 定义了两个不同的值,每个值都有自己的类型。使用右侧的变量 a,它仍然引用与左侧相同的 Sum a b 类型的值。但是我们需要一个不同的类型,根据 fmap

,

不能这样做的原因是,fmap 的结果类型取决于 f 的结果类型,而表达式 a 不依赖。也就是说,您没有约束 f b ~ a

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...