首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Haskell函子隐含定律

Haskell函子隐含定律
EN

Stack Overflow用户
提问于 2011-11-29 12:43:25
回答 4查看 1.8K关注 0票数 22

Typeclassopedia说:

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

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

代码语言:javascript
复制
Law 1: fmap id = id
Law 2: fmap (g . h) = (fmap g) . (fmap h)
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-11-29 13:29:03

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

请记住,Haskell中的FunctorHask类别上的内部函数器,甚至不是所有在Hask上数学上被认为是内部函数器的东西都可以用Haskell来表示。参数多态性的约束排除了能够为它映射的所有对象(类型)指定一个不统一行为的函数器的可能性。

基于this thread,普遍的共识似乎是,对于Haskell Functor实例,第二个定律遵循第一个定律。Edward Kmett says

对于给定的fmap id = idfmap (f . g) = fmap f . fmap g

的自由定理推导而来。

这篇文章发表在很久以前的一篇论文中,但我忘了在哪里。

票数 20
EN

Stack Overflow用户

发布于 2011-11-30 16:53:03

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

代码语言:javascript
复制
data Foo a = Foo a
    deriving Show

instance Functor Foo where
    fmap f (Foo x) = f `seq` Foo (f x)

我们可以验证这是否满足第一定律:

代码语言:javascript
复制
fmap id (Foo x)
= id `seq` Foo (id x)
= Foo (id x)
= Foo x

然而,它违反了第二定律:

代码语言:javascript
复制
> fmap (const 42 . undefined) $ Foo 3
Foo 42
> fmap (const 42) . fmap undefined $ Foo 3
*** Exception: Prelude.undefined

也就是说,我们通常会忽略这些病态的案例。

票数 14
EN

Stack Overflow用户

发布于 2011-11-29 13:20:39

我要说的是,第二定律不是出于有效性的原因,而是作为一个重要的性质而提到的:

第一定律说,在容器中的每一项上映射标识函数没有任何效果。第二种方法是将两个函数的组合映射到容器中的每个项上,这与先映射一个函数,然后再映射另一个函数相同。-类型性百科全书

(我不明白为什么第一定律意味着第二定律,但我不是一个熟练的Haskeller -当你知道发生了什么时,它可能是显而易见的)

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8305949

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档