在 Scala 中编写自由 monad
Composing Free monads in Scala
我想我理解 Free
monad 是什么。我希望我也明白函子 compose 但 monads do not,即如果 M1
和 M2
是 monads 那么 M1[M2]
是 不是 必须是 monad。
我的问题是:
Free
monad 组成吗?
- 假设我们有函子
F1
和 F2
以及它们的组合 F1[F2]
。假设我们还有 Free1
和 Free2
-- Free
monads for F1
and F2
。我们可以只用 Free1
和 Free2
为 F1[F2]
定义一个 Free
monad 吗?
希望我能回答你的问题:
自由 monad 可以组合吗?
否。出于与 "normal" 相同的原因,monad 不会。要编写 monadic bind,我们需要了解一些关于底层 monad 的知识,或者了解自由 monad 情况下的底层仿函数。
希望 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"
在第二种情况下,我们有 f :: g (Free g a)
和 k :: a -> Free f (Free g b)
。我们可以 fmap
,因为这是我们唯一能做的事情:
bind (Pure (Free f)) k = let kf = fmap (fmap k) f -- fmapping inside g ∘ Free g
in = error "not implement"
当我们需要 Free f (Free g b)
时,kf
的类型将是:g (Free g (Free f (Free g b)))
。您将遇到与为任何 Compose m1 m2
编写 monad 实例时相同的问题,我们需要将 "bind layers" 从 g-g-f-g
重新排序为 f-g-g-g
,然后执行此操作我们需要更多地了解 f
和 g
.
如果你想看上面的Scala版本,请评论。不过它会更加晦涩:(
我们可以为 F1[F2] 定义一个只有 Free1 和 Free2 的 Free monad吗
换句话说:
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]
我们可以写一个从 FreeDist[A]
到 FreeComp[A]
的 monad 同态(good 映射)吗?我们不能,原因与前一部分相同。
Scala 版本
Scalaz 有 Free
子类的私有定义,所以我必须自己实现 Free
才能有一个 "runnable" 示例。从 http://eed3si9n.com/learning-scalaz/Free+Monad.html
中删除的一些代码
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] = ???
}
使用它我们可以将 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 _ => ???
}
结果是一样的,我们不能使类型匹配,我们需要将Free[G, Free[F, A]]
转换成Free[F, Free[G, A]]
。
我想我理解 Free
monad 是什么。我希望我也明白函子 compose 但 monads do not,即如果 M1
和 M2
是 monads 那么 M1[M2]
是 不是 必须是 monad。
我的问题是:
Free
monad 组成吗?- 假设我们有函子
F1
和F2
以及它们的组合F1[F2]
。假设我们还有Free1
和Free2
--Free
monads forF1
andF2
。我们可以只用Free1
和Free2
为F1[F2]
定义一个Free
monad 吗?
希望我能回答你的问题:
自由 monad 可以组合吗?
否。出于与 "normal" 相同的原因,monad 不会。要编写 monadic bind,我们需要了解一些关于底层 monad 的知识,或者了解自由 monad 情况下的底层仿函数。
希望 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"
在第二种情况下,我们有 f :: g (Free g a)
和 k :: a -> Free f (Free g b)
。我们可以 fmap
,因为这是我们唯一能做的事情:
bind (Pure (Free f)) k = let kf = fmap (fmap k) f -- fmapping inside g ∘ Free g
in = error "not implement"
当我们需要 Free f (Free g b)
时,kf
的类型将是:g (Free g (Free f (Free g b)))
。您将遇到与为任何 Compose m1 m2
编写 monad 实例时相同的问题,我们需要将 "bind layers" 从 g-g-f-g
重新排序为 f-g-g-g
,然后执行此操作我们需要更多地了解 f
和 g
.
如果你想看上面的Scala版本,请评论。不过它会更加晦涩:(
我们可以为 F1[F2] 定义一个只有 Free1 和 Free2 的 Free monad吗
换句话说:
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]
我们可以写一个从 FreeDist[A]
到 FreeComp[A]
的 monad 同态(good 映射)吗?我们不能,原因与前一部分相同。
Scala 版本
Scalaz 有 Free
子类的私有定义,所以我必须自己实现 Free
才能有一个 "runnable" 示例。从 http://eed3si9n.com/learning-scalaz/Free+Monad.html
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] = ???
}
使用它我们可以将 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 _ => ???
}
结果是一样的,我们不能使类型匹配,我们需要将Free[G, Free[F, A]]
转换成Free[F, Free[G, A]]
。