Haskell Functor暗示法律

Tho*_*ing 21 math haskell functor

Typeclassopedia说:

"类似的论点也表明,满足第一定律的任何Functor实例(fmap id = id)也会自动满足第二定律.实际上,这意味着只需要检查第一定律(通常通过非常简单的归纳法)确保Functor实例有效."

如果是这种情况,为什么我们甚至提到第二个仿函法?

Law 1: fmap id = id
Law 2: fmap (g . h) = (fmap g) . (fmap h)
Run Code Online (Sandbox Code Playgroud)

Tom*_*ett 20

虽然我无法提供证据,但我相信这说的是,由于参数性,只要第一定律成立,类型系统就会执行第二定律.指定这两个规则的原因是,在更一般的数学设置中,您可能有一些类别C,其中完全可以定义从C到其自身的"映射" (即Obj(C )Hom上的一对内部函数(C )分别)遵守第一条规则但不遵守第二条规则,因此不构成仿函数.

请记住,FunctorHaskell中的s是Hask类别的endofunctor,甚至在Haskell 上也不能用数学上被认为是Haskell上的endofunctor的所有内容...参数多态的约束排除了能够指定一个不行为的函子统一地映射它的所有对象(类型).

基于这个主题,普遍的共识似乎是第二个定律从Haskell Functor实例的第一个定律开始.爱德华凯梅特,

给定 fmap id = id,fmap (f . g) = fmap f . fmap g 遵循fmap的自由定理.

这篇文章在很长一段时间内作为一篇文章发表在一篇文章中,但我忘了在哪里.


ham*_*mar 13

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

data Foo a = Foo a
    deriving Show

instance Functor Foo where
    fmap f (Foo x) = f `seq` Foo (f x)
Run Code Online (Sandbox Code Playgroud)

我们可以验证这符合第一定律:

fmap id (Foo x)
= id `seq` Foo (id x)
= Foo (id x)
= Foo x
Run Code Online (Sandbox Code Playgroud)

然而,它打破了第二定律:

> fmap (const 42 . undefined) $ Foo 3
Foo 42
> fmap (const 42) . fmap undefined $ Foo 3
*** Exception: Prelude.undefined
Run Code Online (Sandbox Code Playgroud)

也就是说,我们通常会忽略这种病态病例.

  • 请注意,当您在涉及底部值时使用 seq 区分不同行为时,您就是在“破解”类型系统。haskell 类型形成 Hask 类别,函数是态射,_if_ 你不包括底部。如果您在图片中包含底部,则类似于您的操作表明结果结构不是类别(结合性失败),因此谈论函子也没有意义 (2认同)