为什么monad不会在scala中构成
当Monad是一个应用者并且Applicative是一个Functor时,为什么monad不能编写.你在网上的许多文章中看到了这个继承链(我已经经历过).但是,当Functors和Applicatives组成为什么Monads打破了这个?
有人可以在scala中提供一个演示此问题的简单示例吗?我知道这被问了很多,但没有一个简单的例子就很难理解. 解决方法
首先,让我们从一个简单的问题开始.比方说,我们需要得到一个包含在Future和Option中的两个整数的总和.让我们假设,我们使用猫库.
如果我们使用monad方法(又名flatMap),我们需要: > Future和Option都应该在它们上面定义Monad实例 所以,这是代码(让我们忘记for-comprehension和提升以使其更简单): val fa = OptionT[Future,Int](Future(Some(1))) val fb = OptionT[Future,Int](Future(Some(2))) fa.flatMap(a => fb.map(b => a + b)) //note that a and b are already Int's not Future's 如果你看看OptionT.flatMap来源: def flatMap[B](f: A => OptionT[F,B])(implicit F: Monad[F]): OptionT[F,B] = flatMapF(a => f(a).value) def flatMapF[B](f: A => F[Option[B]])(implicit F: Monad[F]): OptionT[F,B] = OptionT(F.flatMap(value)(_.fold(F.pure[Option[B]](None))(f))) 您会注意到代码非常特定于Option的内部逻辑和结构(fold,None). EitherT,StateT等同样的问题 这里重要的是没有在猫中定义FutureT,所以你可以编写Future [Option [T]],但不能用Option [Future [T]]来做(后来我会证明这个问题是均匀的更通用的). 另一方面,如果您使用Applicative选择合成,您只需要满足一个要求: > Future和Option都应该有针对它们定义的Applicative实例 你不需要任何特殊的变换器用于Option,基本上cat库提供适用于任何Applicative的嵌套类(让我们忘记应用构建器的糖以简化理解): val fa = Nested[Future,Option,Int](Future(Some(1))) val fb = Nested[Future,Int](Future(Some(1))) fa.map(x => (y: Int) => y + x).ap(fb) 我们交换它们: val fa = Nested[Option,Future,Int](Some(Future(1))) val fb = Nested[Option,Int](Some(Future(1))) fa.map(x => (y: Int) => y + x).ap(fb) 作品! 所以是Monad是适用的,选项[Future [T]]仍然是monad(在Future [T]上但不在T本身上)但是它允许你只用Future [T]而不是T操作.为了“合并”使用Future层的选项 – 您必须定义monadic变换器FutureT,以便将Future与Option合并 – 您必须定义OptionT.而且,OptionT在cats / scalaz中定义,但不是FutureT. 一般来说(从here):
正如我在Option和Future中所展示的那样,这种构成甚至都不是可交换的. 作为练习,您可以尝试定义FutureT的flatMap: def flatMapF[B](f: A => F[Future[B]])(implicit F: Monad[F]): FutureT[F,B] = FutureT(F.flatMap(value){ x: Future[A] => val r: Future[F[Future[B]] = x.map(f) //you have to return F[Future[B]] here using only f and F.pure,//where F can be List,Option whatever }) 基本上这种实现的问题是你必须从r中“提取”这里不可能的值,假设你不能从Future中提取值(没有定义comonad),如果我们谈论的话,这是真的“非阻塞”API.这基本上意味着你不能“交换”Future和F,就像Future [F [Future [B]] => F [未来[未来[B]这是自然变换的方式(仿函数之间的态射).这就解释了this general answer的第一条评论:
然而,申请人没有这样的问题 – 你可以很容易地编写它们,但请记住,两个申请人的组成结果可能不是一个单子(但总是一个应用).嵌套[Future,T]不是T上的monad,不管Option和Future都是T上的monad.简单的单词Nested as a class没有flatMap. 阅读: > http://typelevel.org/cats/tut/applicative.html 把它们放在一起(F和G是单子) > F [G [T]]是G [T]上的单子,但不是T 这意味着您可以将Future x Option(又名[Option [T]])组合成一个monad,但是你不能在不知道它们是其他东西的情况下编写Option x Future(又名Future [Option [T]]).除了是单子.你可以将任意两个应用程序组合成一个单独的应用程序,你也可以将任意两个monad组成一个单一的应用程序(但不能组成一个单一的monad). (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |