Rounnar Bjarnason의 "합리적인 가격의 모나드가있는 구성 가능한 응용 프로그램 아키텍처"를 생각해 본 끝에 Scalaz의 비디오에 제공된 예제를 작성하기 시작했습니다. 인터랙트 앱을위한 작가 기반의 인터프리터를 구현할 때 약간 놀랄 것입니다. 작가 자체가 모나드이기 때문에 여기가 상호 작용 무료 모나드를위한 통역으로 ConsoleW를 들어 올리려고 코드,scalar.Coyoneda.liftTF의 문맥 경계
sealed trait Interact[A]
case class Ask(prompt: String) extends Interact[String]
case class Tell(msg: String) extends Interact[Unit]
type W[A] = scalaz.Writer[Vector[String], A]
object ConsoleW extends (Interact ~> W) {
def apply[A](i: Interact[A]) = i match {
case Ask(prompt) =>
println(prompt)
Writer(Vector(prompt), readLine)
case Tell(msg) =>
println(msg)
Writer(Vector.empty,())
}
}
이며, 컴파일러는 나에게 내가 꽤 당황 스럽네요 W.에은 Functor의 바인딩 컨텍스트의 부족을 암시 functor 컨텍스트 바운드는 무료로 제공되어야합니다. 좋아, 그래서 내가 기본적으로 작가 자신의지도 방법을 호출하는 것보다 다른 아무것도하지 않기 때문에 명시 적으로 ... 꽤 바보
implicit val functor = new Functor[W] {
def map[A, B](fa: Writer[Vector[String], A])(f: A => B) =
fa.map(f)
}
을 펑터를 작성했다. 이제 ConsoleW를 통역사로들 수 있습니다. 그러나 ConsoleW로 상호 작용하는 프로그램을 foldMap하려고 시도했을 때 컴파일러는 다시 W에 대한 Monad 컨텍스트의 부족을 암시했습니다! 좋아,이 완전히 예기치 않은 나에게 숟가락 공급을, Scalac ...
val prg: Free[({type f[x] = Coyoneda[Interact, x]})#f, Unit] = ???
import scalaz.std.vector._
implicit val monad = new scalaz.Monad[W] {
def point[A](a: => A) = Writer[Vector[String], A](Vector.empty, a)
def bind[A, B](fa: Writer[Vector[String], A])(f: A => Writer[Vector[String], B]) =
fa.flatMap(f)
}
prg.foldMap(Coyoneda.liftTF(ConsoleW))
지금 모든 컴파일, 프로그램이 실행될 때 모나드는 벡터에 모든 메시지를 기록 할 수있는 작가를 보자. 그러나 이것은 필자가 필자가 실제로 Functor 및 Monad라는 증거를 명시 적으로 제공하지 않고 Writer를 기본 Monad로 사용하여 통역사를 만들고 싶습니다. 이것이 어떻게 풀릴 수 있는지 어떤 생각?
Scalaz 버전, 가져 오기 및 추가 컨텍스트에 대해 더 많이 말할 수 있습니까? 이것은 추가 인스턴스없이 잘 작동 할 것이며, Scala 2.11.5의 Scalaz 7.1.0을 사용한 손쉬운 REPL 세션에서 모든 것이 잘 보입니다. –
@Travis 예 그렇습니다. scalaz._를 가져 왔습니다. import Scalaz._; 그것은 잘 풀렸다. 그러나 만약 내가 scalaz.syntax.monad._; 컴파일에 실패했습니다. 나는 수입에서 무엇을 놓치고 있습니까? – Sheng
알았어요. scalaz.std.vector._를 가져와야합니다. – Sheng