[英]Composing Free monads in Scala
I think I understand what Free
monad is. 我想我明白
Free
monad是什么。 I hope I understand also that functors compose but monads do not , ie if M1
and M2
are monads then M1[M2]
is not necessarily a monad. 我希望我的理解也是仿函数构成 ,但单子没有 ,也就是说,如果
M1
和M2
的单子,然后M1[M2]
不一定是一个单子。
My questions are: 我的问题是:
Free
monads compose ? Free
单子组成吗? F1
and F2
and their composition F1[F2]
. F1
和F2
以及它们的组成F1[F2]
。 Suppose also we have Free1
and Free2
-- Free
monads for F1
and F2
. Free1
和Free2
- F1
和F2
Free
单子。 Can we define a Free
monad for F1[F2]
with just Free1
and Free2
? Free1
和Free2
定义F1[F2]
的Free
monad吗? Hopefully I can answer your question: 希望我能回答你的问题:
No . 不 。 For the same reasons as "normal" monads don't.
出于与“普通”monad相同的原因没有。 To write monadic bind we need to know something about the underlying monad, or about the underlying functor in a free monad case.
要编写monadic 绑定,我们需要了解有关底层monad的信息,或者关于自由monad案例中的底层函子。
Hopefully the Haskell syntax doesn't scare you too much: 希望Haskell语法不会吓到你太多:
type X f g a = Free f (Free g a)
bind :: X f g a -> (a -> X f g b) -> X f g b
bind (Pure (Pure x)) k = k x
bind (Pure (Free f)) k = error "not implemented"
bind _ = error "we don't even consider other cases"
In the second case we have f :: g (Free ga)
and k :: a -> Free f (Free gb)
. 在第二种情况下,我们有
f :: g (Free ga)
和k :: a -> Free f (Free gb)
。 We could fmap
, as it's the only thing we can do: 我们可以
fmap
,因为这是我们唯一可以做的事情:
bind (Pure (Free f)) k = let kf = fmap (fmap k) f -- fmapping inside g ∘ Free g
in = error "not implement"
The type of kf
will be: g (Free g (Free f (Free gb)))
, when we'd need Free f (Free gb)
. 当我们需要
Free f (Free gb)
时, kf
的类型是: g (Free g (Free f (Free gb)))
Free f (Free gb)
。 You'll arrive at the same problem as when writing a monad instance for any Compose m1 m2
, we'd need to reorder "bind layers" from ggfg
to fggg
, and to do that commutation we need to know more about f
and g
. 您将遇到与为任何
Compose m1 m2
monad实例时相同的问题,我们需要重新排序从ggfg
到fggg
“绑定层”,并且为了进行这种换向,我们需要了解更多关于f
和g
。
Please comment, if you want to see the Scala version of above. 如果你想看到上面的Scala版本,请发表评论。 It will be much more obscure though :(
但它会更加模糊:(
In other words given: 换句话说:
type Free1[A] = Free[F1, A]
type Free2[A] = Free[F2, B]
type FreeDist[A] = Free1[Free2[A]] = Free[F1, Free[F2, A]]
type FreeComp[A] = Free[F1[F2[_]], A]
Could we write a monad homomorphism (a good mapping) from FreeDist[A]
to FreeComp[A]
? 我们可以写一个从
FreeDist[A]
到FreeComp[A]
的monad同态(一个很好的映射)吗? We can't, for the same reasons as in a previous part. 我们不能,出于与前一部分相同的原因。
Scalaz has private definitions of subclasses of Free
, so I have to implement Free
myself to have an "runnable" example. Scalaz有
Free
的子类的私有定义,所以我必须自己实现Free
以拥有一个“可运行”的例子。 Some of the code scrapped from http://eed3si9n.com/learning-scalaz/Free+Monad.html 部分代码从http://eed3si9n.com/learning-scalaz/Free+Monad.html中删除
First simplest definition of Free
in Scala: Scala中
Free
第一个最简单的定义:
import scala.language.higherKinds
trait Functor[F[_]] {
def map[A, B](x: F[A])(f: A => B): F[B]
}
sealed trait Free[F[_], A] {
def map[B](f: A => B)(implicit functor: Functor[F]): Free[F, B]
def flatMap[B](f: A => Free[F, B])(implicit functor: Functor[F]): Free[F, B]
}
case class Pure[F[_], A](x: A) extends Free[F, A] {
def map[B](f: A => B)(implicit functor: Functor[F]): Free[F, B] = Pure[F, B](f(x))
def flatMap[B](f: A => Free[F, B])(implicit functor: Functor[F]): Free[F, B] = f(x)
}
case class Bind[F[_], A](x: F[Free[F, A]]) extends Free[F, A] {
def map[B](f: A => B)(implicit functor: Functor[F]): Free[F, B] = Bind {
functor.map[Free[F,A], Free[F,B]](x) { y => y.map(f) }
}
// omitted
def flatMap[B](f: A => Free[F, B])(implicit functor: Functor[F]): Free[F, B] = ???
}
Using that we can translate the Haskell example into Scala: 使用它我们可以将Haskell示例转换为Scala:
type X[F[_], G[_], A] = Free[F, Free[G, A]]
// bind :: X f g a -> (a -> X f g b) -> X f g b
def xFlatMap[F[_], G[_], A, B](x: X[F, G, A], k: A => X[F, G, B])(implicit functorG: Functor[G]): X[F, G, B] =
x match {
case Pure(Pure(y)) => k(y)
case Pure(Bind(f)) => {
// kf :: g (Free g (Free f (Free g b)))
val kf: G[Free[G, Free[F, Free[G, B]]]] = functorG.map(f) { y => y.map(k) }
// But we need Free[F, Free[G, B]]
???
}
// we don't consider other cases
case _ => ???
}
The result is the same, we can't make types match, We'd need transform Free[G, Free[F, A]]
into Free[F, Free[G, A]]
somehow. 结果是一样的,我们不能使类型匹配,我们需要以某种方式将
Free[G, Free[F, A]]
转换为Free[F, Free[G, A]]
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.