简体   繁体   English

monadic liftM和functorial fmap必须相同吗?

[英]Do the monadic liftM and the functorial fmap have to be equivalent?

(Note: I'm phrasing the question using Haskell terminology; answers are welcome to use the same terminology and/or the mathematical language of category theory, including proper mathematical definitions and axioms where I speak of functor and monad laws.) (注意:我正在使用Haskell术语来表达这个问题;欢迎使用相同的术语和/或类别理论的数学语言,包括正确的数学定义和公理,其中我提到了仿函数和monad定律。)

It is well known that every monad is also a functor, with the functor's fmap equivalent to the monad's liftM . 众所周知,每个monad也是一个fmap函数, fmap函数的fmap相当于monad的liftM This makes sense, and of course holds for all common/reasonable monad instances. 这是有道理的,当然适用于所有常见/合理的monad实例。

My question is whether this equivalence of fmap and liftM provably follows from the functor and monad laws. 我的问题是fmapliftM等价性是否可以从functor和monad定律得出。 If so it will be nice to see how, and if not it will be nice to see a counterexample. 如果是这样,很高兴看到如何,如果不是,那么看到一个反例会很好。

To clarify, the functor and monad laws I know are the following: 为了澄清,我所知的仿函数和monad定律如下:

  • fmap idid fmap idid
  • fmap f . fmap g fmap f . fmap gfmap (f . g) fmap f . fmap g fmap (f . g)
  • return x >>= ffx return x >>= f fx
  • x >>= returnx x >>= returnx
  • (x >>= f) >>= gx >>= (\\x -> fx >>= g) (x >>= f) >>= g g≡x x >>= (\\x -> fx >>= g)

I don't see anything in these laws which relates the functor functionality ( fmap ) to the monad functionality ( return and >>= ), and so I find it hard to see how the equivalence of fmap and liftM (defined as liftM fx = x >>= (return . f) ) can be derived from them. 我没有看到这些法律中将函数功能( fmap )与monad功能( return>>= )相关联,因此我发现很难看出fmapliftM的等价性(定义为liftM fx = x >>= (return . f) )可以从它们派生。 Maybe there is an argument for it which is just not straightforward enough for me to spot? 也许有一个争论,这对我来说不够简单? Or maybe I'm missing some laws? 或许我错过了一些法律?

What you have missed is the parametericity law, otherwise known as the free theorem. 您错过的是参数性定律,也称为自由定理。 One of the consequences of parametricity is that all polymorphic functions are natural transformations. 参数化的一个后果是所有多态函数都是自然变换。 Naturality says that any polymorphic function of the form Naturality表示形式的任何多态函数

t :: F a -> G a

where F and G are functors, commutes with fmap : 其中FGfmap函数,与fmap通勤:

t . fmap f = fmap f . t

If we can make something involving liftM that has the form of a natural transformation, then we will have an equation relating liftM and fmap . 如果我们可以做一些涉及liftM东西,它具有自然变换的形式,那么我们将得到一个与liftMfmap相关的方程式。 liftM itself doesn't produce a natural transformation: liftM本身不会产生自然变形:

liftM :: (a -> b) -> m a -> m b
              --       ^______^
              -- these need to be the same

But here's an idea, since (a ->) is a functor: 但这是一个想法,因为(a ->)是一个仿函数:

as :: m a
flip liftM as :: (a -> b) -> m b
              --  F    b  -> G b

Let's try using parametericity on flip liftM m : 让我们尝试在flip liftM m上使用参数:

flip liftM m . fmap f = fmap f . flip liftM m

The former fmap is on the (a ->) functor, where fmap = (.) , so fmap(a ->) fmap = (.)函数上,其中fmap = (.) ,所以

flip liftM m . (.) f = fmap f . flip liftM m

Eta expand Eta扩展

(flip liftM m . (.) f) g = (fmap f . flip liftM m) g
flip liftM m (f . g)     = fmap f (flip liftM m g)
liftM (f . g) m          = fmap f (liftM g m)

This is promising. 这很有希望。 Take g = id : g = id

liftM (f . id) m = fmap f (liftM id m)
liftM f m        = fmap f (liftM id m)

It would suffice to show liftM id = id . 显示liftM id = id就足够了。 That probably follows from its definition: 这可能源于其定义:

liftM id m
   = m >>= return . id
   = m >>= return
   = m

Yep! 是的! Qed. QED。

For this exercise, I found it easier to work with join rather than >>= . 对于本练习,我发现使用join而不是>>=更容易。 A monad can be equivalently defined through return and join , satisfying monad可以通过returnjoin等效地定义,满足

1) join . join = join . fmap join
2) join . return = join . fmap return = id

Indeed, join and >>= are inter-definable: 实际上, join>>=是可以定义的:

x >>= f = join (fmap f x)
join x = x >>= id

And the laws you mentioned correspond to those above (I won't prove this). 你提到的法律与上述法律相对应(我不会证明这一点)。

Then, we have: 然后,我们有:

liftM f x
= { def liftM }
x >>= return . f 
= { def >>= }
join (fmap (return . f) x)
= { def . and $ }
join . fmap (return . f) $ x
= { fmap law }
join . fmap return . fmap f $ x
= { join law 2 }
id . fmap f $ x
= { def id, ., $ }
fmap f x

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM