作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在学习 haskell,其中一个棘手的部分是类型变量。
考虑以下示例:
Prelude> :t fmap
fmap :: Functor f => (a -> b) -> f a -> f b
有类型变量a
和b
,它们可以是任何类型。而 f
是必须实现为 Functor 的类型。
让我们为 fmap
的第一个参数定义一个函数:
Prelude> let replaceWithP = const 'p'
现在,我将函数 replaceWithP
传递给 fmap
并查看类型签名:
Prelude> :t fmap replaceWithP
fmap replaceWithP :: Functor f => f b -> f Char
为什么f a
变成了f b
,为什么不是a
?
最佳答案
一、类型
fmap replaceWithP :: Functor f => f b -> f Char
完全等同于
fmap replaceWithP :: Functor f => f a -> f Char
因为所有类型变量都是隐式通用量化的,所以它们可以随意重命名(这被称为 alpha 转换)。
人们可能仍然想知道 GHC 打印的名称 b
是从哪里来的。毕竟,fmap
的类型中有 f a
,那么为什么 GHC 选择将其重命名为 b
?
这里的“罪魁祸首”是replaceWithP
> :t const
const :: a -> b -> a
> let replaceWithP = const 'p'
> :t replaceWithP
replaceWithP :: b -> Char
因此,b
来自 replaceWithP
的类型。
关于haskell - 类型变量a和b有什么区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44881191/
我是一名优秀的程序员,十分优秀!