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
:
t
是满足上述规则的 Applicative
的实例,并且
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的要求(其实几乎什么都行)。实际上,Identity
是 Functor
和 Applicative
的普通实例,如 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 语言扩展而改变,例如 FlexibleInstances
或 OverlappingInstances
,我不知道还没看懂
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 = id
和 fmap f . fmap g = fmap (f . g)
。
如果我们不这样做,那么你是对的,我们有一种情况 fmap = undefined
,另一种情况 fmap = (<*>) . pure
。但这有点俗气。
我想我在 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 satisfyfmap f x = pure f <*> x
起初我认为这显然是错误的。也就是说,我猜测一定存在满足以下两个条件的类型构造函数t
:
t
是满足上述规则的Applicative
的实例,并且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的要求(其实几乎什么都行)。实际上,Identity
是 Functor
和 Applicative
的普通实例,如 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 语言扩展而改变,例如 FlexibleInstances
或 OverlappingInstances
,我不知道还没看懂
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 = id
和 fmap f . fmap g = fmap (f . g)
。
如果我们不这样做,那么你是对的,我们有一种情况 fmap = undefined
,另一种情况 fmap = (<*>) . pure
。但这有点俗气。