Scala中自由单子的合成

Scala中自由单子的合成,scala,functional-programming,functor,free-monad,Scala,Functional Programming,Functor,Free Monad,我想我明白什么是免费的。我希望我也能理解,函子只构成单子,也就是说,如果M1和M2是单子,那么M1[M2]不一定是单子 我的问题是: Free单子组成吗 假设我们有函子F1和F2及其组合F1[F2]。假设我们还有Free1和Free2--Free单子,用于F1和F2。我们能用Free1和Free2为F1[F2]定义一个Free单子吗 希望我能回答你的问题: 自由单子作曲吗? 不,因为和“正常”单子不一样的原因。要编写一元绑定,我们需要了解一些关于底层单体的信息,或者自由单体情况下的底层函子的信

我想我明白什么是免费的。我希望我也能理解,函子只构成单子,也就是说,如果
M1
M2
是单子,那么
M1[M2]
不一定是单子

我的问题是:

  • Free
    单子组成吗
  • 假设我们有函子
    F1
    F2
    及其组合
    F1[F2]
    。假设我们还有
    Free1
    Free2
    --
    Free
    单子,用于
    F1
    F2
    。我们能用
    Free1
    Free2
    F1[F2]
    定义一个
    Free
    单子吗
      希望我能回答你的问题:

      自由单子作曲吗? 不,因为和“正常”单子不一样的原因。要编写一元绑定,我们需要了解一些关于底层单体的信息,或者自由单体情况下的底层函子的信息

      希望Haskell语法不会让您太害怕:

      X f g a型=自由f(自由g a)
      绑定::X f g a->(a->X f g b)->X f g b
      绑定(纯(纯x))k=kx
      绑定(纯(自由f))k=错误“未实现”
      绑定=错误“我们甚至不考虑其他情况”
      
      在第二种情况下,我们有
      f::g(freega)
      k::a->freeff(freegb)
      。我们可以
      fmap
      ,因为这是我们唯一能做的事情:

      bind(纯(自由f))k=let kf=fmap(fmap k)f--fmapping in g∘ 自由g
      in=错误“未实现”
      
      当我们需要时,
      kf
      的类型将是:
      g(Free g(Free f(Free gb))
      。您将遇到与为任何
      composem1m2
      编写monad实例时相同的问题,我们需要将“绑定层”从
      g-g-g
      重新排序为
      f-g-g
      ,要进行转换,我们需要了解更多关于
      f
      g

      如果您想查看上面的Scala版本,请发表评论。但这将更加模糊:(

      我们能为F1[F2]定义一个只有Free1和Free2的自由单子吗 换言之:

      type Free1[A]=Free[F1,A]
      类型Free2[A]=Free[F2,B]
      键入FreeDist[A]=Free1[Free2[A]=Free[F1,Free[F2,A]]
      输入FreeComp[A]=Free[F1[F2[]],A]
      
      我们可以写一个从
      FreeDist[a]
      FreeComp[a]
      的单子同态(一个很好的映射)吗?我们不能,原因与前面的部分相同


      Scala版本 Scalaz有
      Free
      的子类的私有定义,所以我必须自己实现
      Free
      来创建一个“可运行”的示例

      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]]

      感谢您提供详细的答案。我将使用Haskell符号进行管理。我看不懂Haskell,我希望看到Scala版本。(我还将做一个实验,因为自由似乎应该让我们进行交换,可能是以一种非均匀的方式)。另外,如果我们使用自由单子来实现可扩展的效果,我们可以合成效果,这可以看作是合成不同的单子。但这有点不同,需要另一个答案。