Package

com.thoughtworks.dsl

domains

Permalink

package domains

Visibility
  1. Public
  2. All

Value Members

  1. object scalaz

    Permalink

    Contains interpreters to enable !-notation for Monadic and other keywords in code blocks whose type support scalaz.Bind, scalaz.MonadError and scalaz.MonadTrans.

    Contains interpreters to enable !-notation for Monadic and other keywords in code blocks whose type support scalaz.Bind, scalaz.MonadError and scalaz.MonadTrans.

    Author:

    杨博 (Yang Bo)

    Example:
    1. scalaz.Free.Trampoline is a monadic data type that performs tail call optimization. It can be built from a @reset code block within some !-notation, similar to the each method in ThoughtWorks Each.

      import _root_.scalaz.Trampoline
      import _root_.scalaz.Free.Trampoline
      import com.thoughtworks.dsl.keywords.Monadic._
      import com.thoughtworks.dsl.domains.scalaz._
      import com.thoughtworks.dsl.Dsl.reset
      val trampoline3 = Trampoline.done(3)
      def dslSquare = Trampoline.delay {
        s"This string is produced by a trampoline: ${!trampoline3 * !trampoline3}"
      }: @reset
      dslSquare.run should be("This string is produced by a trampoline: 9")

      !trampoline3 is a shortcut of !Monadic(trampoline3), which will be converted to flatMap calls by our DSL interpreter. Thus, the method dslSquare is equivalent to the following code in scalaz.syntax:

      def scalazSyntaxSquare = trampoline3.flatMap { tmp1 =>
        trampoline3.flatMap { tmp2 =>
          Trampoline.delay {
            s"This string is produced by a trampoline: ${tmp1 * tmp2}"
          }
        }
      }
      scalazSyntaxSquare.run should be("This string is produced by a trampoline: 9")


      A @reset code block can contain try / catch / finally if the monadic data type supports scalaz.MonadError. tryt.scala is a monad transformer that provides scalaz.MonadError, therefore try / catch / finally expressions can be used inside a @reset code block whose return type is TryT[Trampoline, ?].

      import com.thoughtworks.tryt.invariant.TryT, TryT._
      import scala.util.{Try, Success}
      type TryTTransfomredTrampoline[A] = TryT[Trampoline, A]
      val trampolineSuccess0: TryTTransfomredTrampoline[Int] = TryT(Trampoline.done(Try(0)))
      def dslTryCatch: TryTTransfomredTrampoline[String] = TryT(Trampoline.delay(Try {
        try {
          s"Division result: ${!trampoline3 / !trampolineSuccess0}"
        } catch {
          case e: ArithmeticException =>
            s"Cannot divide ${!trampoline3} by ${!trampolineSuccess0}"
        }
      })): @reset
      inside(dslTryCatch) {
        case TryT(trampoline) =>
          trampoline.run should be(Success("Cannot divide 3 by 0"))
      }

      Note that !-notation can be used on both trampoline3 and trampolineSuccess0 even when they are different types, i.e. trampoline3 is a vanilla Trampoline, while trampolineSuccess0 is a TryT-transfomred Trampoline. It is possible because the interpreters of the keywords.Monadic invoke scalaz.MonadTrans.liftM automatically. The above dslTryCatch method is equivalent to the following code in scalaz.syntax:

      def scalazSyntaxTryCatch: TryTTransfomredTrampoline[String] = {
        import _root_.scalaz.syntax.monadError._
        trampoline3.liftM[TryT].flatMap { tmp0 =>
          trampolineSuccess0.flatMap { tmp1 =>
             TryT(Trampoline.delay(Try(s"Division result: ${tmp0 / tmp1}")))
          }
        }.handleError {
          case e: ArithmeticException =>
            trampoline3.liftM[TryT].flatMap { tmp2 =>
              trampolineSuccess0.flatMap { tmp3 =>
                 TryT(Trampoline.delay(Try(s"Cannot divide ${tmp2} by ${tmp3}")))
              }
            }
          case e =>
            e.raiseError[TryTTransfomredTrampoline, String]
        }
      }
      inside(scalazSyntaxTryCatch) {
        case TryT(trampoline) =>
          trampoline.run should be(Success("Cannot divide 3 by 0"))
      }
  2. object task

    Permalink

    Author:

    杨博 (Yang Bo)

Ungrouped