Создание монады Writer в Scala - PullRequest
       6

Создание монады Writer в Scala

0 голосов
/ 14 сентября 2018

Чтобы научиться создавать монады и изучить их внутренние механизмы, я пытаюсь реализовать версию Writer, следуя этой замечательной статье: Вы могли бы изобрести монады!

Проблема, с которой я сталкиваюсь, заключается в том, что я не могу использовать структуры данных, которые я создал для понимания.

Это очищенный фрагмент моего кода:

case class Writer( x: Double, log: String = "  Beginning of log") {
  def flatMap( f: Double => Writer ): Writer = f( x ) match {
    case Writer( fx, msg ) => Writer( fx, log + "\n  " + msg )
  }
  def map( f: Double => Double ): Double = f( x )
}

def outer( x: Double ) = Writer( Math.log( x ), s"Called outer($x)" )
def inner( x: Double ) = Writer( Math.exp( x ), s"Called inner($x)" )

def example( x: Double ): Unit = {
  // This works
  val result = Writer( x ).flatMap {
    y1 => inner(y1).flatMap { y2 => outer(y2) }
  }
  println( result )

  // This works
  val result2 = for { y1 <- Writer(x) } yield {
    for { y2 <- inner( y1 ) } yield {
      for { y3 <- outer( y2 ) } yield y3
    }
  }
  println( result2 )

  // THIS DOESN'T WORK
  val result3 = for {
    y1 <- Writer(x)
    y2 <- inner( y1 )
    y3 <- outer( y2 )
  } yield y3 // Or whatever, it doesn't work
  println( result3 )
}

Мой полный код доступен здесь: Debuggable.scala

  1. Я понимаю, как осмысливается понимание, моя проблема не в этом.
  2. Я прочитал несколько учебных пособий, в том числе: Писатель? Я едва знал ее!
  3. Я попытался понять пример того, как Writer проверяет скаляр: GitHub scalaz WriterT но слишком много шума для меня

Что я не могу понять, так это , чего не хватает в моем коде . Это похоже на то, как реализация скалаза возвращает что-то хорошее для понимания, а затем вы запускаете это с помощью специального метода. Но не могу найти, как это сделать сам

1 Ответ

0 голосов
/ 14 сентября 2018

Вот как вы можете заставить его скомпилировать:

case class Writer(x: Double, log: String = "  Beginning of log") {
  def flatMap(f: Double => Writer): Writer = f(x) match {
    case Writer(fx, msg) => Writer(fx, log + "\n  " + msg)
  }
  def map(f: Double => Double): Writer = Writer(f(x), log)
}

def outer(x: Double) = Writer(Math.log(x), s"Called outer($x)")
def inner(x: Double) = Writer(Math.exp(x), s"Called inner($x)")

def example(x: Double): Unit = {

  val result = Writer(x).flatMap {
    y1 => inner(y1).flatMap { y2 => outer(y2) }
  }
  println(result)

  val result3 = for {
    y1 <- Writer(x)
    y2 <- inner(y1)
    y3 <- outer(y2)
  } yield y3

  println(result3)
}

example(42)

печатает:

Writer(42.0,  Beginning of log
  Called inner(42.0)
  Called outer(1.73927494152050099E18))
Writer(42.0,  Beginning of log
  Called inner(42.0)
  Called outer(1.73927494152050099E18))

Как уже упоминалось в комментариях, вся эта конструкция не является монадой, это скореечто-то вроде «композиции функций в моноиде Double -эндоморфизмов с каротажем».Невозможно заставить ваш второй пример работать (потому что Writer - это не Double, а ваш map занимает только Double => Double), поэтому я удалил его.

...