![](/img/trans.png)
[英]Resources on managing, phasing, composing monads (in Scala or Haskell)
[英]Composing Free monads in Scala
我想我明白Free
monad是什么。 我希望我的理解也是仿函數構成 ,但單子沒有 ,也就是說,如果M1
和M2
的單子,然后M1[M2]
不一定是一個單子。
我的問題是:
Free
單子組成嗎? F1
和F2
以及它們的組成F1[F2]
。 假設我們還有Free1
和Free2
- F1
和F2
Free
單子。 我們可以用Free1
和Free2
定義F1[F2]
的Free
monad嗎? 希望我能回答你的問題:
不 。 出於與“普通”monad相同的原因沒有。 要編寫monadic 綁定,我們需要了解有關底層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 ga)
和k :: a -> Free f (Free gb)
。 我們可以fmap
,因為這是我們唯一可以做的事情:
bind (Pure (Free f)) k = let kf = fmap (fmap k) f -- fmapping inside g ∘ Free g
in = error "not implement"
當我們需要Free f (Free gb)
時, kf
的類型是: g (Free g (Free f (Free gb)))
Free f (Free gb)
。 您將遇到與為任何Compose m1 m2
monad實例時相同的問題,我們需要重新排序從ggfg
到fggg
“綁定層”,並且為了進行這種換向,我們需要了解更多關於f
和g
。
如果你想看到上面的Scala版本,請發表評論。 但它會更加模糊:(
換句話說:
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同態(一個很好的映射)嗎? 我們不能,出於與前一部分相同的原因。
Scalaz有Free
的子類的私有定義,所以我必須自己實現Free
以擁有一個“可運行”的例子。 部分代碼從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]]
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.