为什么我需要在 fmap 的定义中再次调用构造函数,即使我没有应用 f 参数?
Why do I need to call the constructor again in the definition of fmap even when I don't apply the f argument?
我不知道为什么下面的 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?
另一个问题是,这是否会影响性能或仅在编译时发生?
您需要调用构造函数 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 :: a
,First a
的类型 Sum a t
和 t
由 First a
出现的上下文决定。等号两边的两个 First a
定义了两个不同的值,每个都有自己的类型。使用右侧的变量 a
,它仍然引用与左侧相同的类型 Sum a b
的值。但是根据 fmap
.
我们需要不同的类型
关于性能:在编译过程的后期,当 GHC 删除了大部分类型信息时,它会尽力注意何时像这样重建值。这一步捕获了很多情况,但不是全部;有时代码会以这样一种方式进行转换,以至于重构不再明显。
你不能这样做的原因是因为 fmap
的结果类型取决于 f
的结果类型,而表达式 a
则不然。也就是说,你没有约束 f b ~ a
.
我不知道为什么下面的 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?
另一个问题是,这是否会影响性能或仅在编译时发生?
您需要调用构造函数 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 :: a
,First a
的类型 Sum a t
和 t
由 First a
出现的上下文决定。等号两边的两个 First a
定义了两个不同的值,每个都有自己的类型。使用右侧的变量 a
,它仍然引用与左侧相同的类型 Sum a b
的值。但是根据 fmap
.
关于性能:在编译过程的后期,当 GHC 删除了大部分类型信息时,它会尽力注意何时像这样重建值。这一步捕获了很多情况,但不是全部;有时代码会以这样一种方式进行转换,以至于重构不再明显。
你不能这样做的原因是因为 fmap
的结果类型取决于 f
的结果类型,而表达式 a
则不然。也就是说,你没有约束 f b ~ a
.