Haskell:关于hackage Control.Applicative文章中应用函子法的描述中的缺陷?:它说Applicative确定了Functor

gks*_*ato 11 haskell functor hackage applicative

我想我在hackage文章中Control.Applicative发现了一个缺陷.作为应用仿函数法的描述,它说:

class Functor f => Applicative f where
Run Code Online (Sandbox Code Playgroud)

带有应用程序的仿函数,提供嵌入纯表达式(pure)和序列计算的操作,并组合它们的结果(<*>).

最小完整定义必须包括满足以下法则的这些函数的实现:

身分

pure id <*> v = v
Run Code Online (Sandbox Code Playgroud)

组成

pure (.) <*> u <*> v <*> w = u <*> (v <*> w)
Run Code Online (Sandbox Code Playgroud)

同态

pure f <*> pure x = pure (f x)
Run Code Online (Sandbox Code Playgroud)

互换

u <*> pure y = pure ($ y) <*> u
Run Code Online (Sandbox Code Playgroud)

(请注意,这并未说明有关fmap的任何内容)并且它声明这些法律确定了Functor实例:

作为这些法律的结果,Functorf 的实例将满足

fmap f x = pure f <*> x
Run Code Online (Sandbox Code Playgroud)

我一开始以为这显然是错的.也就是说,我猜测必须存在t满足以下两个条件的类型构造函数:

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

如果(且仅当)上述内容正确,则必须重写上述语句

f的Functor实例必须满足

fmap f x = pure f <*> x
Run Code Online (Sandbox Code Playgroud)

由于这些法律,这符合Functor法律.

这显然是正确的,无论我的猜测是否正确.

我的问题是:我猜是正确的吗?有没有t所需的条件?


以下是我自己在试图回答这个问题时的想法.

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

t = Identity
newtype Identity a = Identity {runIdentity :: a}
Run Code Online (Sandbox Code Playgroud)

符合上面的要求1和2(事实上,几乎任何事情都可以).实际上,它Identity通常是一个实例,Functor并且Applicative正如其中所定义的那样Data.Functor.Identity.(这满足fmap f = (pure f <*>).)instance (Functor f)为每种类型定义另一个"实现" ,Take a,两个函数

transf_a, tinv_a :: a -> a
Run Code Online (Sandbox Code Playgroud)

这样的

tinv_a . transf_a = id
Run Code Online (Sandbox Code Playgroud)

(从理论上讲,这很容易).现在定义

instance (Functor Identity) where
 fmap (f :: a->b) = Identity . transf_b . f . tinv_a . runIdentity
Run Code Online (Sandbox Code Playgroud)

这符合Functor法律,如果有的话,是与琐碎的法律不同的实现

x :: a
f :: a -> b
Run Code Online (Sandbox Code Playgroud)

这样的

f x /= transf_b $ f $ tinv_a x
Run Code Online (Sandbox Code Playgroud)

但是我们是否可以在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
Run Code Online (Sandbox Code Playgroud)

可能在Haskell?


编辑

我忘了写一些非常重要的东西.我认识到Control.Applicative作为GHC基础包的一部分,所以我也对我的问题的答案是否随任何GHC语言扩展而改变感兴趣,例如,FlexibleInstances或者OverlappingInstances我还不了解.

G P*_*lip 14

Haskell中的任何类型最多只能有一个实例Functor,所以你的猜测是不正确的:因为没有类型t可以存在两种不同的实现Applicative.见:http://article.gmane.org/gmane.comp.lang.haskell.libraries/15384

  • 自由定理的一个非常好的结果! (3认同)
  • 类型`a - > a`的唯一函数是`id`,所以`transf_a`和`tinv_a`都是`id`和`transf_a.tinv_a = id`非常简单.(达到底部,但[道德正确](http://www.cs.ox.ac.uk/jeremy.gibbons/publications/fast+loose.pdf).) (3认同)