根据Monad的应用定义Functor是更好的,反之亦然? [英] Is it better to define Functor in terms of Applicative in terms of Monad, or vice versa?

查看:107
本文介绍了根据Monad的应用定义Functor是更好的,反之亦然?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个普遍的问题,与任何一段代码无关。

假设你有一个类型 T a 可以给出一个 Monad 的实例。由于每个monad通过分配 pure = return (< *>),所以是 Applicative )= ap ,然后每个应用程序通过 fmap fx = pure f * c>来获得 Functor x ,先定义 Monad 的实例,然后再给出 T > Applicative Functor



的实例有点落后于我。如果我在做数学而不是编程,我会认为我会首先证明我的对象是一个函数,然后继续添加限制,直到我还将它展示为monad。我知道Haskell只是受到了类别理论的启发,显然当构建证明时使用的技术并不是编写有用程序时使用的技术,但我希望从Haskell社区获得意见。从 Monad 下降到 Functor 是否更好?或从 Functor Monad

解决方案

我倾向于编写并首先写入 Functor 实例。因为如果您使用 LANGUAGE DeriveFunctor 编译指示,那么数据Foo a = Foo a派生(Functor)当你的 Applicative 可以比你的<$ $更普遍时C $ C>单子。例如,这是一个 Err 数据类型

 数据Err ea = Err [e] |确定一个派生函数(Functor)

实例(Err e)其中
pure = Ok
Err es< *> Err es'= Err(es ++ es')
Err es< *> _ =错误
_< *> Err es = Err es
Ok f <*> Ok x = Ok(fx)

实例Monad(Err e)其中
return =纯
错误>> = _ =错误
Ok a >> = f = fa

上面我定义了 Functor -to - Monad 顺序,并且单独采用每个实例都是正确的。不幸的是, Applicative Monad 实例不符合: ap (*)(>>)和<$ c明显不同$ c $($>)。

  Errhi*< Errbye== Errhibye
Errhi`ap` Errbye== Errhi

为了达到敏感目的,特别是一旦申请人/单体提案在大家手中,这些应该一致。如果您定义了实例Applicative(Err e),其中{pure = return; (< *>)= ap} 然后他们对齐。然后,最后,你可能能够仔细地分开 Applicative Monad 中的区别,以便它们在良性方面表现不同 - 例如具有更简单或更高效的 Applicative 实例。这实际上发生得相当频繁,我觉得陪审团对于良性意味着什么以及在你的实例应该对齐什么类型的观察下仍然存在一些问题。也许一些最合群的用法是在Facebook的Haxl项目中, Applicative 实例比 > Monad 实例,因此以一些相当严重的未观察到的副作用为代价,效率更高。



无论如何,if他们不同,记录它。


This is a general question, not tied to any one piece of code.

Say you have a type T a that can be given an instance of Monad. Since every monad is an Applicative by assigning pure = return and (<*>) = ap, and then every applicative is a Functor via fmap f x = pure f <*> x, is it better to define your instance of Monad first, and then trivially give T instances of Applicative and Functor?

It feels a bit backward to me. If I were doing math instead of programming, I would think that I would first show that my object is a functor, and then continue adding restrictions until I have also shown it to be a monad. I know Haskell is merely inspired by Category Theory and obviously the techniques one would use when constructing a proof aren't the techniques one would use when writing a useful program, but I'd like to get an opinion from the Haskell community. Is it better to go from Monad down to Functor? or from Functor up to Monad?

解决方案

I tend to write and see written the Functor instance first. Doubly so because if you use the LANGUAGE DeriveFunctor pragma then data Foo a = Foo a deriving ( Functor ) works most of the time.

The tricky bits are around agreement of instances when your Applicative can be more general than your Monad. For instance, here's an Err data type

data Err e a = Err [e] | Ok a deriving ( Functor )

instance Applicative (Err e) where
  pure = Ok
  Err es <*> Err es' = Err (es ++ es')
  Err es <*> _       = Err es
  _      <*> Err es  = Err es
  Ok  f  <*> Ok  x   = Ok (f x)

instance Monad (Err e) where
  return = pure
  Err es >>= _ = Err es
  Ok  a  >>= f = f a

Above I defined the instances in Functor-to-Monad order and, taken in isolation, each instance is correct. Unfortunately, the Applicative and Monad instances do not align: ap and (<*>) are observably different as are (>>) and (*>).

Err "hi" <*>  Err "bye" == Err "hibye"
Err "hi" `ap` Err "bye" == Err "hi"

For sensibility purposes, especially once the Applicative/Monad Proposal is in everyone's hands, these should align. If you defined instance Applicative (Err e) where { pure = return; (<*>) = ap } then they will align.

But then, finally, you may be capable of carefully teasing apart the differences in Applicative and Monad so that they behave differently in benign ways---such as having a lazier or more efficient Applicative instance. This actually occurs fairly frequently and I feel the jury is still a little bit out on what "benign" means and under what kinds of "observation" should your instances align. Perhaps some of the most gregarious use of this is in the Haxl project at Facebook where the Applicative instance is more parallelized than the Monad instance, and thus is far more efficient at the cost of some fairly severe "unobserved" side effects.

In any case, if they differ, document it.

这篇关于根据Monad的应用定义Functor是更好的,反之亦然?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆