2
무료 모나드에 대해 배우고 있으며 스칼라에 두 개의 도메인 특정 언어를 정의하는 데 사용하는 간단한 예제를 작성했습니다.무료 Monads 스태킹
첫 번째 모나드는 저장소의 부작용을 처리합니다. 상태를 관리하기 위해 상태 모나드를 사용하는 통역사를 구현했지만 실제 프로그램에서는 데이터베이스를 사용합니다.
두 번째 모나드는 IO를 처리합니다.
import cats.data.State
import cats.{Id, ~>}
import cats.free.Free
import cats.free.Free.liftF
final case class Todo(title: String, body: String)
def represent(todo: Todo) = s"${todo.title}: ${todo.body}"
sealed trait CRUDActionA[T]
final case class Find(key: String) extends CRUDActionA[Option[Todo]]
final case class Add(data: Todo) extends CRUDActionA[Unit]
type CRUDAction[T] = Free[CRUDActionA, T]
def find(key: String): CRUDAction[Option[Todo]] = liftF[CRUDActionA, Option[Todo]](Find(key))
def add(data: Todo): CRUDAction[Unit] = liftF[CRUDActionA, Unit](Add(data))
type TodosState[A] = State[List[Todo], A]
val repository: CRUDActionA ~> TodosState = new (CRUDActionA ~> TodosState) {
def apply[T](fa: CRUDActionA[T]): TodosState[T] = fa match {
case Add(todo) => State.modify(todos => todos :+ todo)
case Find(title) => State.inspect(todos => todos find (_.title == title))
}
}
sealed trait IOActionA[T]
final case class Out(str: String) extends IOActionA[Unit]
type IOAction[T] = Free[IOActionA, T]
def out(str: String): IOAction[Unit] = liftF[IOActionA, Unit](Out(str))
val io: IOActionA ~> Id = new (IOActionA ~> Id) {
override def apply[A](fa: IOActionA[A]): Id[A] = fa match {
case Out(todo) => println(todo)
}
}
다음, 나는이 두 가지 "프로그램"
def addNewTodo: Free[CRUDActionA, Option[Todo]] = for {
_ <- add(Todo(title = "Must do", body = "Must do something"))
todo <- find("Must do")
} yield todo
def outProgram(todo: Todo): IOAction[Unit] = for {
_ <- out(represent(todo))
} yield()
을 넣어
val (_, mayBeTodo) = (addNewTodo foldMap repository run List()).value
outProgram(mayBeTodo.get).foldMap(io)
내가 여기까지 이상에서 이해하고이를 실행하고 나는 싶습니다 수 있습니다 프로그램을 작성하고 통역사는 다음을 지원합니다.
def fullProgram = for {
_ <- add(Todo(title = "Must do", body = "Must do something"))
todo <- find("Must do") // This is an option!!!
_ <- out(represent(todo)) // But represent expects a Todo
} yield()
(210)
그래서 질문은 다음과 같습니다
- 은 어떻게 "fullProgram"에 함께 두 개의 모나드를 쌓을 수 있나요? 그때
find
에 의해 반환되는 옵션 [도도] 처리하고, 어떻게 - 1 &이 질문에
represent
몇 가지 프로젝트를 생성하기 위해 노력하고 거기 이러한 것들은 상용구를 쓰지 않고도 가능합니다. 예 : FreeDSL -> https://github.com/ISCPIF/freedsl – jopasserat