免费的 Monad 解释器
Free Monad interpreter
我正在关注 Chris Myers 关于 Free Monads 的演讲,但是当我实现解释器时出现编译错误
package object example {
import cats._
import cats.data._
import cats.free._
import cats.implicits._
case class Property(Id: Int, post: String)
type Script[A] = Free[AppAction, A]
sealed trait AppAction[A] {
def lift: Script[A] = Free.liftF(this)
}
case class FetchById(propertyId: Int) extends AppAction[Property]
case class Save(property: Property) extends AppAction[Unit]
case class Log(message: String) extends AppAction[Unit]
def fetchById(id: Int): Script[Property] = FetchById(id).lift
def save(property: Property): Script[Unit] = Save(property).lift
def log(message: String): Script[Unit] = Log(message).lift
def updatePost(propertyId: Int, post: String): Script[Property] = {
for {
property <- fetchById(propertyId)
p1 = property.copy(post = post)
_ <- log("Updating")
_ <- save(p1)
} yield p1
}
object TestInterp extends (AppAction ~> Id) {
def apply[A](fa: AppAction[A]): Id[A] = fa match {
case FetchById(_) => Property(1, "2000")
case Save(_) => ()
case Log(msg) => println(msg)
}
def run[A](script: Script[A]) = script.foldMap(this)
}
}
我导入了猫,特别是 cats.Id 但我在测试解释器中得到了 "Expression of type Property does not conform to cats.Id"。我什至在 Id monad 中明确包装了 fetchById 的结果,但它不起作用。
在for
-表达式中
p1 <- property.copy(post = post)
不是单子绑定步骤。就像定义辅助变量 p1
的简单赋值一样。这在这里似乎有效:
import cats._
import cats.data._
import cats.free._
import cats.implicits._
case class Property(id: Int, post: String)
sealed trait AppAction[A] {
def lift: Script[A] = Free.liftF(this)
}
case class FetchById(propertyId: Int) extends AppAction[Property]
case class Save(property: Property) extends AppAction[Unit]
case class Log(message: String) extends AppAction[Unit]
type Script[A] = Free[AppAction, A]
def fetchById(id: Int): Script[Property] = FetchById(id).lift
def save(property: Property): Script[Unit] = Save(property).lift
def log(message: String): Script[Unit] = Log(message).lift
def updatePost(propertyId: Int, post: String): Script[Unit] = {
for {
property <- fetchById(propertyId)
p1 = property.copy(post = post)
_ <- log("Updating")
_ <- save(p1)
} yield()
}
object TestInterp extends (AppAction ~> Id) {
def apply[A](fa: AppAction[A]): Id[A] = fa match {
case FetchById(_) => Property(1, "2000")
case Save(_) => ()
case Log(msg) => println(msg)
}
def run[A](script: Script[A]) = script.foldMap(this)
}
我正在关注 Chris Myers 关于 Free Monads 的演讲,但是当我实现解释器时出现编译错误
package object example {
import cats._
import cats.data._
import cats.free._
import cats.implicits._
case class Property(Id: Int, post: String)
type Script[A] = Free[AppAction, A]
sealed trait AppAction[A] {
def lift: Script[A] = Free.liftF(this)
}
case class FetchById(propertyId: Int) extends AppAction[Property]
case class Save(property: Property) extends AppAction[Unit]
case class Log(message: String) extends AppAction[Unit]
def fetchById(id: Int): Script[Property] = FetchById(id).lift
def save(property: Property): Script[Unit] = Save(property).lift
def log(message: String): Script[Unit] = Log(message).lift
def updatePost(propertyId: Int, post: String): Script[Property] = {
for {
property <- fetchById(propertyId)
p1 = property.copy(post = post)
_ <- log("Updating")
_ <- save(p1)
} yield p1
}
object TestInterp extends (AppAction ~> Id) {
def apply[A](fa: AppAction[A]): Id[A] = fa match {
case FetchById(_) => Property(1, "2000")
case Save(_) => ()
case Log(msg) => println(msg)
}
def run[A](script: Script[A]) = script.foldMap(this)
}
}
我导入了猫,特别是 cats.Id 但我在测试解释器中得到了 "Expression of type Property does not conform to cats.Id"。我什至在 Id monad 中明确包装了 fetchById 的结果,但它不起作用。
在for
-表达式中
p1 <- property.copy(post = post)
不是单子绑定步骤。就像定义辅助变量 p1
的简单赋值一样。这在这里似乎有效:
import cats._
import cats.data._
import cats.free._
import cats.implicits._
case class Property(id: Int, post: String)
sealed trait AppAction[A] {
def lift: Script[A] = Free.liftF(this)
}
case class FetchById(propertyId: Int) extends AppAction[Property]
case class Save(property: Property) extends AppAction[Unit]
case class Log(message: String) extends AppAction[Unit]
type Script[A] = Free[AppAction, A]
def fetchById(id: Int): Script[Property] = FetchById(id).lift
def save(property: Property): Script[Unit] = Save(property).lift
def log(message: String): Script[Unit] = Log(message).lift
def updatePost(propertyId: Int, post: String): Script[Unit] = {
for {
property <- fetchById(propertyId)
p1 = property.copy(post = post)
_ <- log("Updating")
_ <- save(p1)
} yield()
}
object TestInterp extends (AppAction ~> Id) {
def apply[A](fa: AppAction[A]): Id[A] = fa match {
case FetchById(_) => Property(1, "2000")
case Save(_) => ()
case Log(msg) => println(msg)
}
def run[A](script: Script[A]) = script.foldMap(this)
}