Friday, April 15, 2011

ScalaFp 04 (Control)






Expect frequent changes.





Control


Here is an aspect of computations: control.


Here is ControlModule.
The abstract control methods are _withC, pushC and pushP.
The extra concrete control methods are _resetC and _shiftC.






package com.imaginej

package control

trait ControlModule {
type M[+Z] <: Control[Z]
type P[Z]
type C1[Y, Z] = M[Y] => M[Z]
type C2[Y, Z] = C1[Y, Z] => M[Z]
type C3[Y, Z] = C2[Y, Z] => M[Y]
def _withC[Y, Z](implicit p: P[Z]): C3[Y, Z]
def _resetC[Z](implicit p: P[Z]): M[Z] => M[Z] =
_.pushP
def _shiftC[Y, Z](implicit p: P[Z]): C3[Y, Z] =
c2 =>
_withC apply { (c1: C1[Y, Z]) =>
c2(_.pushC(c1).pushP).pushP
}
trait Control[+A] { self: M[A] =>
def pushC[C >: A, B, D >: B](c1: C1[C, D]): M[D]
def pushP[B >: A](implicit p: P[B]): M[B]
}
}




ControlMonads


The extra concrete control monad methods are _withCC and _shiftCC.
Also extra methods like reflect and * can be defined.






package com.imaginej

package monad

package control

import monad.MonadModule
import com.imaginej.control.ControlModule

trait ControlMonadModule
extends MonadModule
with ControlModule {
type M[+Z] <: ControlMonad[Z]
type CC1[Y, Z] = Y => M[Z]
type CC2[Y, Z] = CC1[Y, Z] => M[Z]
type CC3[Y, Z] = CC2[Y, Z] => M[Y]
private def c2cc[Y, Z](implicit p: P[Z]): C3[Y, Z] => CC3[Y, Z] =
f => c3 =>
f apply { (c1: C1[Y, Z]) =>
val c2 = (y: Y) => c1(_return(y))
c3(c2)
}
def _withCC[Y, Z](implicit p: P[Z]): CC3[Y, Z] =
c2cc apply _withC
def _shiftCC[Y, Z](implicit p: P[Z]): CC3[Y, Z] =
c2cc apply _shiftC
trait ControlMonad[+A]
extends Monad[A]
with Control[A] { self: M[A] =>
def reflect[C >: A, B](implicit p: P[B]): M[C] =
_shiftCC apply { (sc: C => M[B]) =>
this flatMap sc
}
def *[C >: A, B](mb: M[B])(implicit p: P[(C, B)]): M[(C, B)] =
for {
c <- this.reflect
b <- mb.reflect
} yield (c, b)
}
}




Control Transformed Monads


Here is controlTransformedMonadModule.
It makes use of a type ToM[+Z] = FromM[ValOrExc[M, Z]].
The abstract methods flatMap, _withC, pushC and pushP can now be defined.
Also a method runSControl is defined.


Note: The definition of _withC makes use of asInstanceOf.






package com.imaginej

package monad

package control.transformed

import monad.control.ControlMonadModule
import monad.transformed.TransformedMonadModule

trait ControlTransformedMonadModule
extends TransformedMonadModule
with ControlMonadModule {
type M[+Y] <: ControlTransformedMonadTrait[Y]
type Ans
type Res
case class Prompt[M[_], Z](
_1: C2[Ans, Z] => C2[Ans, Res],
_2: C2[Ans, Res] => Option[C2[Ans, Z]])
type P[Z] = Prompt[M, Z]
implicit val prompt: P[Res] =
Prompt(identity, Some(_))
// note: do not start with underscore
def resetC(m_r: M[Res]): M[Res] =
_resetC apply m_r
def shiftC(c2: C2[Ans, Res]) =
_shiftC apply c2
def shiftCC(cc2: CC2[Ans, Res]) =
_shiftCC apply cc2
//
trait ValOrExc[M[_], +Z]
case class Val[M[_], +Z](z: Z) extends ValOrExc[M, Z]
case class Exc[M[_], Z](
c1: C1[Ans, Z],
c2: C2[Ans, Res]) extends ValOrExc[M, Z]
type ToM[+Z] = FromM[ValOrExc[M, Z]]
type In[-Z] = Unit
override def _lift[Z] =
_.map(Val(_))
// note: only place where asInstanceOf is used
def _withC[Y, Z](implicit p: P[Z]): C3[Y, Z] =
c2 =>
_closeT {
_fromReturn {
Exc(
((my: M[Y]) => my).asInstanceOf[C1[Ans, Y]],
p._1(c2.asInstanceOf[C2[Ans, Z]]))
}
}
trait ControlTransformedMonadTrait[+A]
extends TransformedMonadTrait[A]
with ControlMonad[A] { self: M[A] =>
override def flatMap[B](af_mb: A => M[B]) = {
_closeT {
this.openT flatMap {
case Val(a) =>
af_mb(a).openT
case Exc(c1, c2) =>
_fromReturn(Exc(c1(_).flatMap(af_mb), c2))
}
}
}
override def pushC[C >: A, B, D >: B](c: C1[C, D]): M[D] =
c(this)
override def pushP[D >: A](implicit p: P[D]): M[D] = {
_closeT {
this.openT flatMap {
case v@Val(_) =>
_fromReturn(v)
case Exc(c1, c2) =>
p._2(c2) match {
case someC2@Some(_) =>
someC2.get(c1).openT
case None =>
_fromReturn(Exc(c1(_).pushP(p), c2))
}
}
}
}
def runControl[B >: A](u: Unit)(i: FromIn[B]): FromOut[B] = {
this.openT flatMap {
case Val(b) =>
_fromReturn(b)
case Exc(_, _) =>
throw new Exception("you forgot to push a prompt")
} run i
}
}
}




Control Transformed Monad Instances


Here are some control transformed monad instances.







ControlTransformedIdentityMonad.






package com.imaginej

package monad

package control.instances

import instances.IdentityMonadObject
import control.transformed.ControlTransformedMonadModule

abstract class ControlTransformedIdentityMonadModule(
implicit override val monadObject: IdentityMonadObject.type )
extends ControlTransformedMonadModule {
type MonadModuleType = IdentityMonadObject.type
type M[+Z] = ControlTransformedIdentityMonad[Z]
type Out[+Z] = Z
def _closeT[Z] =
ControlTransformedIdentityMonad[Z](_)
case class ControlTransformedIdentityMonad[+A](val openT: ToM[A])
extends ControlTransformedMonadTrait[A] {
def run[B >: A](u: Unit): B =
runControl(u) ()
}
}

import monad.MonadModule.identityMonad

object Int_Int_ControlTransformedIdentityMonadObject
extends ControlTransformedIdentityMonadModule {
type Ans = Int
type Res = Int
}

object Unit_Int_ControlTransformedIdentityMonadObject
extends ControlTransformedIdentityMonadModule {
type Ans = Unit
type Res = Int
}

object Int_Unit_ControlTransformedIdentityMonadObject
extends ControlTransformedIdentityMonadModule {
type Ans = Int
type Res = Unit
}

object Unit_Unit_ControlTransformedIdentityMonadObject
extends ControlTransformedIdentityMonadModule {
type Ans = Unit
type Res = Unit
}





ControlTransformedTraversableMonad.






package com.imaginej

package monad

package control.instances

import instances.TraversableMonadObject
import control.transformed.ControlTransformedMonadModule

abstract class ControlTransformedTraversableMonadModule(
implicit override val monadObject: TraversableMonadObject.type)
extends ControlTransformedMonadModule {
type MonadModuleType = TraversableMonadObject.type
type M[+Z] = ControlTransformedTraversableMonad[Z]
type Out[+Z] = Traversable[Z]
def _closeT[Z] =
ControlTransformedTraversableMonad[Z](_)
case class ControlTransformedTraversableMonad[+A](val openT: ToM[A])
extends ControlTransformedMonadTrait[A] {
def run[B >: A](u: Unit): Traversable[B] =
runControl(u) ()
}
}

import monad.MonadModule.traversableMonad

object Int__Int_Char_ControlTransformedTraversableMonadObject
extends ControlTransformedTraversableMonadModule {
type Ans = Int
type Res = (Int, Char)
}

object Unit_Unit_ControlTransformedTraversableMonadObject
extends ControlTransformedTraversableMonadModule {
type Ans = Unit
type Res = Unit
}




Implicit Control Transformed Monads


It is convenient to define implicit control transformed monads for later usage.






import instances.Int_Int_ControlTransformedIdentityMonadObject
import instances.Unit_Int_ControlTransformedIdentityMonadObject
import instances.Int_Unit_ControlTransformedIdentityMonadObject
import instances.Unit_Unit_ControlTransformedIdentityMonadObject
import instances.Int__Int_Char_ControlTransformedTraversableMonadObject
import instances.Unit_Unit_ControlTransformedTraversableMonadObject

object ControlMonadModule {
implicit def int_Int_ControlTransformedIdentityMonadObject =
Int_Int_ControlTransformedIdentityMonadObject
implicit def unit_Int_ControlTransformedIdentityMonadObject =
Unit_Int_ControlTransformedIdentityMonadObject
implicit def int_Unit_ControlTransformedIdentityMonadObject =
Int_Unit_ControlTransformedIdentityMonadObject
implicit def unit_Unit_ControlTransformedIdentityMonadObject =
Unit_Unit_ControlTransformedIdentityMonadObject
implicit def int__Int_Char_ControlTransformedTraversableMonadObject =
Int__Int_Char_ControlTransformedTraversableMonadObject
implicit def unit_Unit_ControlTransformedTraversableMonadObject =
Unit_Unit_ControlTransformedTraversableMonadObject
}





Application


Here is an application.






package com.imaginej

package apps

object UsingControlMonads {

import monad.control.instances._

def usingInt_Int_ControlTransformedIdentityMonad() {
import Int_Int_ControlTransformedIdentityMonadObject._
lazy val computation =
resetC {
shiftCC { c =>
c(7)
} >= { i =>
_return(i + 1)
} >= { j =>
_return(2 * j)
}
}
println {
computation run ()
}
}
def usingInt_Unit_ControlTransformedIdentityMonad() {
import Int_Unit_ControlTransformedIdentityMonadObject._
lazy val computation =
resetC {
shiftCC { c =>
c(7)
_return(())
} >= { i =>
_return(i + 1)
} >= { j =>
_return(2 * j)
}
}
println {
computation run ()
}
}
def usingInt__Int_Char_ControlTransformedTraversableMonad() {
import monad.instances.TraversableMonadObject._close
import Int__Int_Char_ControlTransformedTraversableMonadObject._
implicit def traversableToM[Z](zs: Traversable[Z]): M[Z] =
_liftT(_close(zs))
val computation =
resetC {
List(1, 2) * List('a', 'b')
}
println {
computation run ()
}
}
def usingUnit_Unit_ControlTransformedIdentityMonad() {
import Unit_Unit_ControlTransformedIdentityMonadObject._
def _println(s: String) = _return(println(s))
lazy val computation =
resetC {
println("A")
shiftCC { c =>
println("B")
c()
_println("C")
} >> {
println("D")
shiftCC { c =>
println("E")
c()
_println("F")
} >>
_println("G")
}
}
computation run ()
import java.util.{ Timer, TimerTask }
resetC {
println(" look, Ma ...")
shiftCC { c =>
println("wait 5 secs ...")
new Timer().schedule(new TimerTask {
def run() = c()
}, 5000)
_return(())
} >> {
_println("... no threads!")
}
} run ()
}
def main(args: Array[String]) {
usingInt_Int_ControlTransformedIdentityMonad()
usingInt_Unit_ControlTransformedIdentityMonad()
usingInt__Int_Char_ControlTransformedTraversableMonad()
usingUnit_Unit_ControlTransformedIdentityMonad()
}
}





Running the application yields.




$ scala com.imaginej.apps.UsingControlMonads
16
()
List((1,a), (1,b), (2,a), (2,b))
A
B
D
E
G
F
C
look, Ma ...
wait 5 secs ...
... no threads!
^C$

No comments:

Post a Comment