haskell - Haskell:试图理解 fmap 的类型(+)(1)
问题描述
我试图理解为什么没有类型错误fmap (+) (1)
我确实理解以下顺序:
Prelude> :t fmap
fmap :: Functor f => (a -> b) -> f a -> f b
Prelude> :t (+)
(+) :: Num a => a -> a -> a # like a-> b with b = a -> a
Prelude> :t fmap (+)
fmap (+) :: (Functor f, Num a) => f a -> f (a -> a)
Prelude> :t fmap (+) (Just 1)
fmap (+) (Just 1) :: Num a => Maybe (a -> a) # f=Maybe is implied by the Just constructor
Prelude>
我预计会出现类型错误,fmap (+) (1)
因为(1)没有隐含的函子,而是我得到:
Prelude> :t (1)
(1) :: Num p => p
Prelude> :t (+)
(+) :: Num a => a -> a -> a
Prelude> :t fmap (+)
fmap (+) :: (Functor f, Num a) => f a -> f (a -> a)
Prelude> :t fmap (+) (1)
fmap (+) (1) :: (Functor f, Num a, Num (f a)) => f (a -> a) ## why ??
Prelude>
为什么是这样 ?
同样,我不明白的类型fmap (+) id
:
Prelude> :t fmap (+)
fmap (+) :: (Functor f, Num a) => f a -> f (a -> a)
Prelude> :t id
id :: a -> a
Prelude> :t fmap (+) id
fmap (+) id :: Num a => a -> a -> a ## why no error ?
Prelude>
解决方案
数字文字可以适合任何类型,只要它是数字类型(在 class 中Num
)。
GHC 在开放世界假设下工作,即使一个类型现在不属于一个实例,它也可能在未来。这是因为可以编写一个新模块并在那里声明一个实例,我们需要单独编译。
对于数字类型,这意味着即使一个类型现在不是数字,它也可能在以后出现。
假设我们写reverse 1
. 它看起来不对,因为reverse
需要一个列表,而1
不是一个列表。或者是吗?即使[a]
现在不是数字,也可能是将来,因此类型reverse 1
是Num [a] => [a]
,而不是类型错误。当然,一般情况下我们不会有Num [a]
实例,但GHC不能假设。
在您的具体示例中,fmap
想要一个f a
并且您通过(1)
,这与1
. 在这里,这个数字文字被实例化为Num (f a) => f a
,以便进行类型检查。
fmap (+) (1) :: (Functor f, Num a, Num (f a)) => f (a -> a)
需要上述约束Num (f a)
才能1
在 type 中进行解释f a
。Thenf
必须是函子,因为fmap
需要它,并且我们必须Num a
因为(+)
需要它的参数是数字(的参数(+)
有类型a
,它的结果有类型a -> a
,其中a
必须是数字)。由于返回类型为 ,我们f (a -> a)
再次得到结果(+)
。
关于fmap (+) id
,这个比较简单。这里id :: (->) a a
,就是id :: f a
where f = (->) a
,恰好是一个函子。对于这个函子,我们有 that fmap = (.)
,即功能组合运算符。因此,fmap (+) id
意味着(.) (+) id
,或者(+) . id
简单地说(+)
。
推荐阅读
- python - 我的解释器已被命令“git clean -d -f”删除
- mysql - 计算具有特定值的行之间的时间差
- django - 如何在 django 的基于类的视图中设置表单集
- android - 使用 AGP 7.0.0+ 可以替代“registerGeneratedResFolders”吗?
- python - Python 抓取特定的 JS 数据
- windows-installer - MSI 在重大升级期间在 ARP 中添加重复条目
- pine-script - 脚本触发警报不正确
- javascript - React Material UI 滑块
- amazon-sumerian - 如何在 AWS Sumerian 的 HTML 3D 实体中添加 CSS 文件?
- vue.js - Vuetify v-data 表获取索引