Haskell:hackage Control.Applicative 文章中对应用函子法则的描述存在缺陷?:它说 Applicative determines Functor

Haskell: Flaw in the description of applicative functor laws in the hackage Control.Applicative article?: it says Applicative determines Functor

我想我在 the hackage article for Control.Applicative 中发现了一个缺陷。 作为应用函子定律的描述,它说:

class Functor f => Applicative f where

A functor with application, providing operations to embed pure expressions (pure), and sequence computations and combine their results (<*>).

A minimal complete definition must include implementations of these functions satisfying the following laws:

identity

pure id <*> v = v

composition

pure (.) <*> u <*> v <*> w = u <*> (v <*> w)

homomorphism

pure f <*> pure x = pure (f x)

interchange

u <*> pure y = pure ($ y) <*> u

(请注意,这并没有说明任何关于 fmap 的内容)并且它指出这些法则决定了 Functor 实例:

As a consequence of these laws, the Functor instance for f will satisfy

fmap f x = pure f <*> x

起初我认为这显然是错误的。也就是说,我猜测一定存在满足以下两个条件的类型构造函数t

  1. t 是满足上述规则的 Applicative 的实例,并且
  2. instance (Functor t)有两种不同的实现方式 (即有两个不同的函数 fmap1, fmap2 :: (a->b) -> (t a->t b), 满足函子定律)。

如果(且仅当)以上是正确的,上面的语句必须改写为

The Functor instance for f must satisfy

fmap f x = pure f <*> x

As a consequence of these laws, this satisfies the Functor laws.

这显然是正确的,不管我猜对不对

我的问题是我的猜测是否正确?有符合条件的t吗?


下面是我在尝试自己回答这个问题时的想法的解释。

如果我们只是数学家对实际的Haskell编程不感兴趣,我们可以很容易地肯定地回答这个问题。事实上,

t = Identity
newtype Identity a = Identity {runIdentity :: a}

满足上面1和2的要求(其实几乎什么都行)。实际上,IdentityFunctorApplicative 的普通实例,如 Data.Functor.Identity 中所定义。 (这满足fmap f = (pure f <*>)。) 要定义 instance (Functor f) 的另一个 "implementation",对于每个类型 a,取两个函数

transf_a, tinv_a :: a -> a

这样

tinv_a . transf_a = id

(这很容易理论上设置)。现在定义

instance (Functor Identity) where
 fmap (f :: a->b) = Identity . transf_b . f . tinv_a . runIdentity

这满足 Functor 法则,如果有

x :: a
f :: a -> b

这样

f x /= transf_b $ f $ tinv_a x

但我们能否在Haskell中做到这一点并不明显。是这样的:

class (Isom a) where
 transf, tinv :: a -> a

instance (Isom a) where
 transf = id
 tinv = id

specialized instance (Isom Bool) where
 transf = not
 tinv = not

可能在 Haskell?


编辑

我忘了写一些很重要的东西。我认识到 Control.Applicative 是 GHC 基础包的一部分,所以我也很想知道我的问题的答案是否会随着任何 GHC 语言扩展而改变,例如 FlexibleInstancesOverlappingInstances,我不知道还没看懂

Haskell 中的任何类型最多可以有一个 Functor 的实例,因此您的猜测不正确:对于 no,类型 t(不管它是否是Applicative的实例)是否存在instance (Functor t)的两种不同实现。参见:http://article.gmane.org/gmane.comp.lang.haskell.libraries/15384

它是一个属性类型的a -> a,它只有两个居民,即id :: a -> a(定义为id x = x)和bottom :: a -> a定义为bottom = error "Infinite loop."

如果我们将自己限制在第一种情况 "reasonable",我们就会得出一个重要的数学定理,即最多有一个类型为 forall a. forall b. (a -> b) -> f a -> f b 的函数 fmap满足 fmap id = idfmap f . fmap g = fmap (f . g)

如果我们不这样做,那么你是对的,我们有一种情况 fmap = undefined,另一种情况 fmap = (<*>) . pure。但这有点俗气。