【发布时间】:2017-07-03 08:43:40
【问题描述】:
我正在学习 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?
【问题讨论】:
-
GHCi打印出来的名字在这里没有什么特殊含义。
-
好的,所以
b可以是任意类型。 -
a和b可能属于不同的类型,但并非必须如此。f是一个多态类型,必须有函子约束。 -
那么当一个函数具有以下签名
a -> b,那么a类型不必与b类型不同?可以是同一类型吗? -
首先,类型变量的标识不对应于用于命名它们的文字字符,除非在特定类型的本地范围内。所以
forall a b . a -> b和forall a b . b -> a是精确地 相同的类型。其次,事实上,a -> b并不意味着a和b必须不同——一个类型变量可以采用任何类型,包括另一个类型变量。
标签: haskell