Math Haskell函子隐含定律

Math Haskell函子隐含定律,math,haskell,functor,Math,Haskell,Functor,说: “类似的论证还表明,任何满足第一定律(fmap id=id)的函子实例也将自动满足第二定律。实际上,这意味着只有第一定律需要检查(通常通过非常简单的归纳法),以确保函子实例有效。” 如果是这样,为什么我们还要提到第二函子定律 Law 1: fmap id = id Law 2: fmap (g . h) = (fmap g) . (fmap h) 我要说的是,第二定律并不是出于有效性的原因而被提及的,而是作为一项重要的财产: 第一定律说,在每个项目上映射标识函数 在容器中没有效果。第二种

说:

“类似的论证还表明,任何满足第一定律(fmap id=id)的函子实例也将自动满足第二定律。实际上,这意味着只有第一定律需要检查(通常通过非常简单的归纳法),以确保函子实例有效。”

如果是这样,为什么我们还要提到第二函子定律

Law 1: fmap id = id
Law 2: fmap (g . h) = (fmap g) . (fmap h)

我要说的是,第二定律并不是出于有效性的原因而被提及的,而是作为一项重要的财产:

第一定律说,在每个项目上映射标识函数 在容器中没有效果。第二种说法是映射 容器中每个项上的两个函数的组合是 与先映射一个函数,然后映射另一个函数相同。 ---类型分类视界


(我不明白为什么第一定律意味着第二定律,但我不是一个熟练的哈斯凯尔人——当你知道发生了什么事情时,这可能是显而易见的)

似乎人们意识到第二定律源于第1定律。因此,当文档最初编写时,它可能被认为是一个独立的需求


(就我个人而言,我不相信这一论点,但由于我自己还没有时间解决细节问题,我在这里表示怀疑。)

虽然我不能给出证据,但我相信这是说,由于类型系统执行第二定律,只要第一定律成立。指定这两个规则的原因是,在更一般的数学设置中,您可能有一些类别C,其中完全可以定义从C到自身的“映射”(即Obj(C)和Hom(C)上的一对内函数)它遵守第一条规则,但不遵守第二条规则,因此不能构成函子

请记住,Haskell中的
函子
s是类Hask上的内函子,甚至在数学上被认为是Hask上的内函子的一切都不能用Haskell表示。。。参数多态性的约束排除了能够为其映射的所有对象(类型)指定行为不一致的函子的可能性

基于此,普遍的共识似乎是,对于Haskell
函子
实例,第二定律遵循第一定律。爱德华·克米特

给定
fmap id=id
fmap(f.g)=fmap f。fmap g
遵循免费 fmap定理

很久以前,这篇文章作为旁白发表在一篇论文中,但我忘了在哪里


使用
seq
,我们可以编写满足第一条规则但不满足第二条规则的实例

data Foo a = Foo a
    deriving Show

instance Functor Foo where
    fmap f (Foo x) = f `seq` Foo (f x)
我们可以验证这是否满足第一定律:

fmap id (Foo x)
= id `seq` Foo (id x)
= Foo (id x)
= Foo x
但是,它违反了第二条定律:

> fmap (const 42 . undefined) $ Foo 3
Foo 42
> fmap (const 42) . fmap undefined $ Foo 3
*** Exception: Prelude.undefined

也就是说,我们通常忽略这种病理情况。

您提供的链接似乎是关于
函子
实例的唯一性,而不是第一定律暗示第二定律。。。关于后者。不要对自己太苛刻——这并没有那么明显。这里有一篇关于从自由定理到第二个Fnuctor定律的更详细的文章,@David有一个拼写错误:“Fnuctor”->“Functor”注意,当你在涉及底部值的不同行为之间用seq进行区分时,你是在“破解”类型系统。haskell类型构成Hask类别,如果不包括底部,则函数为态射。如果在图片中包含底部,类似于您的操作会显示结果结构不是类别(关联性失败),因此谈论函子也没有意义