繁体   English   中英

免费monad比使用IO monads的普通旧特性有什么优势?

[英]What is the advantage of Free monads over plain old traits with IO monads?

所以我一直在深入研究FP概念,我喜欢封装在IO monad中的纯度概念。 然后我读了这篇文章 ,并认为IO monad确实不像使用Free Monads那样解耦(?)。

所以我开始使用这些概念做我的东西,然后我意识到traits实现了将结构与执行分离的相同目的。 更糟糕的是,使用免费monad有很多限制,例如错误处理和将上下文边界和隐式参数传递到解释器/实现中。

所以我的问题是:使用它们有什么好处? 我如何解决我刚才提到的问题(隐式参数和错误处理)? Free Monands的使用是否限制在学术领域,还是可以在行业中使用?

编辑:一个解释我怀疑的例子

  import cats.free.Free._
  import cats.free.Free
  import cats.{Id, ~>}

  import scala.concurrent.Future

  sealed trait AppOpF[+A]

  case class Put[T](key: String, value: T) extends AppOpF[Unit]

  case class Delete(key: String) extends AppOpF[Unit]
  //I purposely had this extend AppOpF[T] and not AppOpF[Option[T]]
  case class Get[T](key: String) extends AppOpF[T]

  object AppOpF {
    type AppOp[T] = Free[AppOpF, T]

    def put[T](key: String, value: T): AppOp[Unit] = liftF[AppOpF, Unit](Put(key, value))

    def delete(key: String): AppOp[Unit] = liftF[AppOpF, Unit](Delete(key))

    def get[T](key: String): AppOp[T] = liftF[AppOpF, T](Get(key))

    def update[T](key: String, func: T => T): Free[AppOpF, Unit] = for {
      //How do I manage the error here, if there's nothing saved in that key?
      t <- get[T](key)
      _ <- put[T](key, func(t))
    } yield ()


  }

  object AppOpInterpreter1 extends (AppOpF ~> Id) {
    override def apply[A](fa: AppOpF[A]) = {
      fa match {
        case Put(key,value)=>
          ???
        case Delete(key)=>
          ???
        case Get(key) =>
          ???
      }
    }
  }
  //Another implementation, with a different context monad, ok, that's good
  object AppOpInterpreter2 extends (AppOpF ~> Future) {
    override def apply[A](fa: AppOpF[A]) = {
      fa match {
        case a@Put(key,value)=>
          //What if I need a Json Writes or a ClassTag here??
          ???
        case a@Delete(key)=>
          ???
        case a@Get(key) =>
          ???
      }
    }
  }

IO monad的自由代数具有相同的目的 - 将程序构建为纯数据结构。 如果将Free与IO的一些具体实现进行比较,IO可能会获胜。 它将具有更多功能和专业特性,可帮助您快速移动并快速开发您的程序。 但这也意味着你将在一个IO实现上拥有一个主要的供应商锁定。 无论您选择哪个IO,它都将是一个具体的IO库,可能存在性能问题,错误或支持问题 - 谁知道。 由于程序与实现之间的紧密耦合,将程序从一个供应商更改为另一个供应商将花费您很多。

另一方面,自由代数允许您在不谈论程序实现的情况下表达您的程序。 它以您可以轻松测试并独立更改它们的方式将您的需求与实现分开。 作为另一个好处,Free允许您根本不使用IO。 您可以在其中包含标准Futures,java的标准CompletableFuture或任何其他第三方并发原语,并且您的程序仍然是纯粹的。 为此,Free将需要额外的样板(正如您在示例中所示)并且灵活性较低。 所以选择权是你的。

还有另一种方式 - 最终无标签。 这种方法试图平衡来自双方的专业人员,提供更少的供应商锁定,但仍然不像免费代数那样冗长。 值得一试。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM