下面是一个函数的定义:
fmap :: (a -> b) -> f a -> f b
你们能解释一下具体是什么意思吗?我不明白的是f a:f b为什么可以这样写?我的意思是,为什么它语法正确并且编译良好?
我认为应该只有一个变量(a -> b) -> a -> b或(a -> b) -> f -> f其他(a -> b) -> c -> d
再一次,问题不在于函数的含义,而在于语法是否正确。
下面是一个函数的定义:
fmap :: (a -> b) -> f a -> f b
你们能解释一下具体是什么意思吗?我不明白的是f a:f b为什么可以这样写?我的意思是,为什么它语法正确并且编译良好?
我认为应该只有一个变量(a -> b) -> a -> b或(a -> b) -> f -> f其他(a -> b) -> c -> d
再一次,问题不在于函数的含义,而在于语法是否正确。
您接受“正常”map功能的签名map :: (a -> b) -> [a] -> [b]吗?
现在假设不是[a]我们写了List a(与 比较Maybe a),所以签名读的是map :: (a -> b) -> List a -> List b。此签名在带有 的表格(a -> b) -> f a -> f b上f = List。
该函数fmap :: (a -> b) -> f a -> f b是map对其他类型构造函数(如Maybe.
那么 Haskell[1] 类型签名由 3 个元素组成
现在,对于您的示例,我们有 2 个元素。a, b, 和f是类型变量,然后我们有函数箭头。
a并b具有 kind *,这意味着它们可以按原样由具体类型实例化。f另一方面,有种类* -> *[2]。这意味着f不能以与 and 相同的方式实例a化b。它需要用一个类型实例化,该类型采用一种类型,*然后产生一个具体类型。
例如,Maybe必须先给出另一种类型,比如Int,然后才能构造该类型的值。例如Just 1 :: Maybe Int,但wat :: Maybe没有意义。因此,应用程序f a与将值函数f应用于 value相同a,但类型除外。你甚至有部分应用!
所以读f a -> f b作“一个函数,它将采用某种类型f,将其应用于某种类型a,并返回一个f应用于某种类型的类型值b”。
[1] 哈斯克尔我的意思是香草哈斯克尔。类型运算符、对 N 个类型进行排序等使事情变得复杂。
[2] 这不是正常功能->。它谈论的是类型而不是值。
Haskell 中的语法Type1 Type2意味着类型的应用。例如,您可能已经看到 type Maybe Integer。它的工作原理Maybe是这样定义的:
data Maybe a = ...
注意类型变量a。这意味着我们必须先应用于Maybe某种类型,然后才能将其用作类型本身。在Maybe Integer中,这a被设置为Integer。
现在在问题中,我们有f a,即一个类型变量应用于另一个类型变量。这意味着f可以是Maybe期望应用于另一种类型的a东西,并且可以是Integer本身就是一种类型的东西。