任何与fmap具有相同多态类型的函数都必须等于fmap吗?
Any function with the same polymorphic type as fmap must be equal to fmap?
我正在阅读 Haskell 的第二版编程,我遇到了这句话:
... there is only one way to make any given parameterised type into a functor, and hence any function with the same polymorphic type as fmap
must be equal to fmap
.
不过我觉得这不对。我可以看到每个 Functor
类型只有一个 valid 定义 fmap
,但我肯定可以定义任意数量的 [=14 类型的函数=] 哪个不等价?
为什么会这样?或者,这只是作者的错误?
这是一个错误。以下是一些与 fmap
类型相同的函数示例,用于不是 fmap
:
的列表
\f -> const []
\f -> concatMap (replicate 2 . f)
\f -> map (f . head) . chunksOf 2
\f -> map f . reverse
还有很多。一般来说,给定一个函数 ixf
从列表长度到不大于该长度的数字列表(即列表中的有效索引),我们可以构建
maybeIt'sFmapLol :: (Int -> [Int]) -> (a -> b) -> [a] -> [b]
maybeIt'sFmapLol ixf elemf xs = [map elemf xs !! ix | ix <- ixf (length xs)]
使用 Int
的适当惰性变体来处理无限列表。可以为其他类似容器的仿函数构建类似的函数模式。
你误读了作者的意思。
...any function with the same polymorphic type as fmap
...
这意味着,任何具有签名
的函数
Functor f => (a -> b) -> f a -> f b
必须等同于 fmap
。 (当然,除非您允许最低值。)
这个说法是正确的;如果您尝试定义这样一个函数,则可以很容易地看到:因为除了它是一个函子之外,您对 f
一无所知,因此获得非 ⊥ f b
值的唯一方法是通过 fmapping f a
一个。
引用中的逻辑含义不太明确:
there is only one way to make any given parameterised type into a functor, and hence any function with the same polymorphic type as fmap must be equal to fmap.
我认为作者的意思是有,因为Functor f => (a -> b) -> f a -> f b
函数必须调用fmap
,并且因为fmap
总是唯一 参数化类型的有效函子映射,任何 Functor f => (a -> b) -> f a -> f b
实际上也会遵守函子法则,即它将是 the fmap
.
我同意“因此”的措辞有点糟糕,但原则上引用是正确的。
我认为引用是指这种情况。假设我们定义了一个参数化类型:
data F a = .... -- whatever
为此我们不仅可以编写一个,还可以编写两个 fmap
实现
fmap1 :: (a -> b) -> F a -> F b
fmap2 :: (a -> b) -> F a -> F b
满足函子定律
fmap1 id = id
fmap1 (f . g) = fmap1 f . fmap1 g
fmap2 id = id
fmap2 (f . g) = fmap2 f . fmap2 g
根据这些假设,我们有 fmap1 = fmap2
。
这是与 fmap
的多态类型关联的 "free theorem" 的理论结果(请参阅 Lemma 1 下的注释)。
从实用上讲,这确保了我们从 deriving Functor
获得的实例是唯一可能的实例。
我正在阅读 Haskell 的第二版编程,我遇到了这句话:
... there is only one way to make any given parameterised type into a functor, and hence any function with the same polymorphic type as
fmap
must be equal tofmap
.
不过我觉得这不对。我可以看到每个 Functor
类型只有一个 valid 定义 fmap
,但我肯定可以定义任意数量的 [=14 类型的函数=] 哪个不等价?
为什么会这样?或者,这只是作者的错误?
这是一个错误。以下是一些与 fmap
类型相同的函数示例,用于不是 fmap
:
\f -> const []
\f -> concatMap (replicate 2 . f)
\f -> map (f . head) . chunksOf 2
\f -> map f . reverse
还有很多。一般来说,给定一个函数 ixf
从列表长度到不大于该长度的数字列表(即列表中的有效索引),我们可以构建
maybeIt'sFmapLol :: (Int -> [Int]) -> (a -> b) -> [a] -> [b]
maybeIt'sFmapLol ixf elemf xs = [map elemf xs !! ix | ix <- ixf (length xs)]
使用 Int
的适当惰性变体来处理无限列表。可以为其他类似容器的仿函数构建类似的函数模式。
你误读了作者的意思。
...any function with the same polymorphic type as
fmap
...
这意味着,任何具有签名
的函数Functor f => (a -> b) -> f a -> f b
必须等同于 fmap
。 (当然,除非您允许最低值。)
这个说法是正确的;如果您尝试定义这样一个函数,则可以很容易地看到:因为除了它是一个函子之外,您对 f
一无所知,因此获得非 ⊥ f b
值的唯一方法是通过 fmapping f a
一个。
引用中的逻辑含义不太明确:
there is only one way to make any given parameterised type into a functor, and hence any function with the same polymorphic type as fmap must be equal to fmap.
我认为作者的意思是有,因为Functor f => (a -> b) -> f a -> f b
函数必须调用fmap
,并且因为fmap
总是唯一 参数化类型的有效函子映射,任何 Functor f => (a -> b) -> f a -> f b
实际上也会遵守函子法则,即它将是 the fmap
.
我同意“因此”的措辞有点糟糕,但原则上引用是正确的。
我认为引用是指这种情况。假设我们定义了一个参数化类型:
data F a = .... -- whatever
为此我们不仅可以编写一个,还可以编写两个 fmap
实现
fmap1 :: (a -> b) -> F a -> F b
fmap2 :: (a -> b) -> F a -> F b
满足函子定律
fmap1 id = id
fmap1 (f . g) = fmap1 f . fmap1 g
fmap2 id = id
fmap2 (f . g) = fmap2 f . fmap2 g
根据这些假设,我们有 fmap1 = fmap2
。
这是与 fmap
的多态类型关联的 "free theorem" 的理论结果(请参阅 Lemma 1 下的注释)。
从实用上讲,这确保了我们从 deriving Functor
获得的实例是唯一可能的实例。