Saturday, November 12, 2011

ScalaFX: Jumping Frogs Puzzle







Expect frequent changes.





ScalaFX example: Jumping Frogs Puzzle


This is my first ScalaFX example. It is a jumping frogs puzzle.




Here is the top level JumpingFrogsPuzzle application code.




Note that the definition of stage makes use of a kind of object literal notation (one of the main goals of the ScalaFX library is to provide a DSL to use JavaFX in a more convenient way).






object JumpingFrogsPuzzle extends JFXApp {

import theViewValues.canvasShape
import theViewValues.stoneShapes
import theViewValues.dummyFrogShape
import theView.optionalFrogShapes

val frogShapes =
for {
optionalFrogShape <- optionalFrogShapes
} yield {
optionalFrogShape match {
case Some(frogShape) => frogShape
case None => dummyFrogShape
}
}

stage = new Stage {
title = TITLE
scene = new Scene {
content =
canvasShape :: stoneShapes ::: frogShapes
}
}
}




theView


The top level application code uses an object theView.






import theViewValues.optionalFrogShapes

object theView extends View(theModel, theControl, optionalFrogShapes)




theViewValues


The top level application code also uses an object theViewValues.






object theViewValues {
val canvasShape =
theCanvasShape

val stoneShapes =
for {
i <- STONE_NUMBER_LIST
} yield StoneShape(i)

val dummyFrogShape =
theDummyFrogShape

import theModelValues.optionalFrogMap

val optionalFrogShapes =
for {
i <- STONE_NUMBER_LIST
} yield {
if (i < NUMBER_OF_FROGS) {
Some(new GreenFrogShape(i, optionalFrogMap(i).get))
} else if (i == NUMBER_OF_FROGS) {
None
} else {
Some(new RedFrogShape(i, optionalFrogMap(i).get))
}
}
}




theControl and theModel


The theView code uses objects theControl and theModel.






object theControl extends Control

import theModelValues.optionalFrogMap

object theModel extends Model(optionalFrogMap)




Shapes


The theViewValues code uses shapes code.






case object theCanvasShape extends Rectangle {
width = CANVAS_WIDTH
height = CANVAS_HEIGHT
fill = CANVAS_FILL
}

case class StoneShape(position: Int) extends Rectangle {
x = FIRST_STONE_X + STONE_STEP * position
y = STONE_Y
width = STONE_WIDTH
height = STONE_HEIGHT
fill = STONE_FILL
stroke = STONE_STROKE
strokeWidth = STONE_STROKE_WIDTH
}

abstract class FrogShape(startPosition: Int, frog: Frog) extends Circle {
val getFrog = frog
centerX = FIRST_FROG_CENTER_X + STONE_STEP * startPosition
centerY = FROG_CENTER_Y
radius = FROG_RADIUS
}

class GreenFrogShape(startPosition: Int, frog: Frog)
extends FrogShape(startPosition, frog) {
fill = GREEN_FROG_FILL
}

class RedFrogShape(startPosition: Int, frog: Frog)
extends FrogShape(startPosition, frog) {
fill = RED_FROG_FILL
}

case object theDummyFrogShape extends FrogShape(-1, theDummyFrog)




theModelValues


The theModel code uses an object theModelValues.






object theModelValues {
val optionalFrogMap =
(for {
i <- STONE_NUMBER_LIST
} yield {
if (i < NUMBER_OF_FROGS) {
i -> Some(new LeftFrog())
} else if (i == NUMBER_OF_FROGS) {
i -> None
} else {
i -> Some(new RightFrog())
}
}).toMap
}




Frogs


The frog shapes code uses frogs code.






trait Frog {
def movesToRight: Boolean

def movesToLeft: Boolean
}

class LeftFrog() extends Frog {
def movesToRight = true

def movesToLeft = false
}

class RightFrog() extends Frog {
def movesToRight = false

def movesToLeft = true
}

case object theDummyFrog extends Frog {
def movesToRight = false

def movesToLeft = false
}




Control code


Here is the control code.






class Control {
def update(model: Model, view: View) {
view.optionalFrogShapes.foreach {
case Some(frogShape) => frogShape.onMouseClicked =
if (model.canJumpOneRight(frogShape.getFrog)) {
view.jumpOneRight(frogShape)
} else if (model.canJumpTwoRight(frogShape.getFrog)) {
view.jumpTwoRight(frogShape)
} else if (model.canJumpOneLeft(frogShape.getFrog)) {
view.jumpOneLeft(frogShape)
} else if (model.canJumpTwoLeft(frogShape.getFrog)) {
view.jumpTwoLeft(frogShape)
}
case None =>
}
}
}




Model code


Here is the model code.






class Model(var optionalFrogMap: Map[Int, Option[Frog]]) {
private def isAtRight(i: Int) =
i == NUMBER_OF_STONES - 1

private def isAtRightOrOneButRight(i: Int) =
i == NUMBER_OF_STONES - 1 || i == NUMBER_OF_STONES - 2

private def isAtLeft(i: Int) =
i == 0

private def isAtLeftOrOneButLeft(i: Int) =
i == 0 || i == 1

private def canMoveOneRightAt(i: Int) =
!isAtRight(i) &&
optionalFrogMap(i + 1) == None

private def canMoveTwoRightAt(i: Int) =
!isAtRightOrOneButRight(i) &&
optionalFrogMap(i + 1).get.movesToLeft &&
optionalFrogMap(i + 2) == None

private def canMoveOneLeftAt(i: Int) =
!isAtLeft(i) &&
optionalFrogMap(i - 1) == None

private def canMoveTwoLeftAt(i: Int) =
!isAtLeftOrOneButLeft(i) &&
optionalFrogMap(i - 1).get.movesToRight &&
optionalFrogMap(i - 2) == None

def positionOf(frog: Frog) =
(for {
(i, optionalFrog) <- optionalFrogMap
if (optionalFrog == Some(frog))
} yield i).head

def canJumpOneRight(frog: Frog) =
canMoveOneRightAt(positionOf(frog))

def canJumpTwoRight(frog: Frog) =
canMoveTwoRightAt(positionOf(frog))

def canJumpOneLeft(frog: Frog) =
canMoveOneLeftAt(positionOf(frog))

def canJumpTwoLeft(frog: Frog) =
canMoveTwoLeftAt(positionOf(frog))

def update(next: Int => Int)(frog: Frog) {
val j = positionOf(frog)
optionalFrogMap = for {
entry@(i, _) <- optionalFrogMap
} yield {
if (i == j) {
(i, None)
} else if (i == next(j)) {
(i, optionalFrogMap(j))
} else {
entry
}
}
}
}




View code


Here is the view code.






class View(model: Model, control: Control, val optionalFrogShapes: List[Option[FrogShape]]) {
control.update(model, this)

private def update(length: Int, next: (Double, Double) => Double)(frogShape: FrogShape) {
val frogShapeCenterX = FIRST_FROG_CENTER_X + STONE_STEP * model.positionOf(frogShape.getFrog)
val frogShapeCenterY = FROG_CENTER_Y

Timeline(Seq(
at(length * TIME s) {
frogShape.centerY -> (frogShapeCenterY - length * STONE_STEP / 2)
},
at(length * TIME s) {
frogShape.centerX -> next(frogShapeCenterX, length * STONE_STEP / 2)
},
at(2 * length * TIME s) {
frogShape.centerY -> frogShapeCenterY
},
at(2 * length * TIME s) {
frogShape.centerX -> next(frogShapeCenterX, length * STONE_STEP)
}
)).play()
}

def jumpOneRight(frogShape: FrogShape) {
update(1, _ + _)(frogShape)
model.update(_ + 1)(frogShape.getFrog)
control.update(model, this)
}

def jumpTwoRight(frogShape: FrogShape) {
update(2, _ + _)(frogShape)
model.update(_ + 2)(frogShape.getFrog)
control.update(model, this)
}

def jumpOneLeft(frogShape: FrogShape) {
update(1, _ - _)(frogShape)
model.update(_ - 1)(frogShape.getFrog)
control.update(model, this)
}

def jumpTwoLeft(frogShape: FrogShape) {
update(2, _ - _)(frogShape)
model.update(_ - 2)(frogShape.getFrog)
control.update(model, this)
}
}


Saturday, August 27, 2011

ScalaSpace






Expect frequent changes.





ScalaSpace


The idea behind the ScalaSpace library is to model concurrent work in a data driven way.






Here is the Types object.
The type Work represents work that can be registered with a space by a worker.








package types

object Types {
type Work[X] = PartialFunction[X, Unit]
}




Spawner


Here is the Spawner object.
The method spawn spawns work w by applying it to data x.






package spawner

import java.util.Timer
import java.util.TimerTask

import types.Types.Work

object Spawner {
def spawn[X](x: X, w: Work[X]) {
val timer = new Timer()
timer.schedule(
new TimerTask() {
def run() = {
w(x)
timer.cancel()
}
}, 0)
}
}




Space


Here is the Space class.
It has a data queue xs and a work queue ws.
The method put either spawns the first work from the work queue with data (and removes the work from the work queue) or puts data in the data queue (when no work from the work queue can be applied to it).
The method reg either spawns work with the first data from the data queue (and removes the data from the data queue) or puts work in the work queue (when it cannot be applied to data from the data queue).






package space;

import scala.collection.immutable.Queue

import types.Types.Work

import spawner.Spawner.spawn

class Space[X] {
private var xs: Queue[X] = Queue()
private var ws: Queue[Work[X]] = Queue()

override def toString = "(" + xs + ")"

def put(x: X) = synchronized {
ws find (_.isDefinedAt(x)) match {
case None =>
xs = xs :+ x
case Some(w) =>
ws = ws diff Queue(w)
spawn(x, w)
}
}

def reg(w: Work[X]) = synchronized {
xs find (w.isDefinedAt(_)) match {
case None =>
ws = ws :+ w
case Some(x) =>
xs = xs diff Queue(x)
spawn(x, w)
}
}
}




Worker


Here is the Worker abstract class.
A worker has a reference to a space.
The abstract method work speaks for itself.






package worker

import space.Space

abstract class Worker[X](space: Space[X]) {
def work(): Unit
}




PingPongApp


We are ready for the first application PingPongApp.
Details will be explained in what follows: for now, just admire it's simplicity.






package pingpong.globals

import scala.math.random
import scala.math.round

import pingpong.table.Table
import pingpong.player.Pinger
import pingpong.player.Ponger
import pingpong.umpire.Umpire

object Globals {
val table = Table()

private def playTime = round(1000 * random)

val players =
Pinger("pinger_1", table, playTime) ::
Pinger("pinger_2", table, playTime) ::
Ponger("ponger_1", table, playTime) ::
Ponger("ponger_2", table, playTime) ::
Nil

val umpire = Umpire("_umpire_", players, table)

}

package apps

import pingpong.globals.Globals._
import pingpong.elements.Ping

object PingPongApp {
def main(args: Array[String]) = {
umpire.work()
for(player <- players) {
player.work()
}
table.put(Ping)
}
}




PingPong


The sealed abstract class PingPong and the case objects implementing it represent the data that drive the application.






package pingpong.elements

sealed abstract class PingPong
case object Ping extends PingPong
case object Pong extends PingPong
case object Over extends PingPong
case object Done extends PingPong




Table


The case class Table represents the pingpong table.






package pingpong.table

import space.Space

import pingpong.elements.PingPong

case class Table() extends Space[PingPong]




Player


The Player abstract class and its implementation case classes Pinger and Ponger represent the pingpong players.
A pinger can either ping, work with a Pong from a ponger which can either succeed or fail, or stop, work with a Done from the umpire.
A ponger can either pong, work with a Ping from a pinger which can either succeed or fail, or stop, work with a Done from the umpire.






package pingpong.player

import worker.Worker

import pingpong.table.Table
import pingpong.elements.PingPong
import pingpong.elements.Pong
import pingpong.elements.Ping
import pingpong.elements.Over
import pingpong.elements.Done

abstract class Player(name: String, table: Table, playTime: Long)
extends Worker[PingPong](table) {
override def toString: String = name
}


case class Pinger(name: String, table: Table, playTime: Long)
extends Player(name, table, playTime) {
def work() = table.reg {
case Pong =>
if (scala.math.random < 0.95) {
Thread.sleep(playTime)
println(this + " ping")
table.put(Ping)
} else {
Thread.sleep(playTime)
println(this + " over")
table.put(Over)
}
work()
case Done =>
println(this + " stop")
}
}

case class Ponger(name: String, table: Table, playTime: Long)
extends Player(name, table, playTime) {
def work() = table.reg {
case Ping =>
if (scala.math.random < 0.95) {
Thread.sleep(playTime)
println(this + " pong")
table.put(Pong)
} else {
Thread.sleep(playTime)
println(this + " over")
table.put(Over)
}
work()
case Done =>
println(this + " stop")
}
}




Umpire


The Umpire case class represents the pingpong umpire.
The umpire can stop the pingpong game, work with an Over from a pinger or a ponger.






package pingpong.umpire

import worker.Worker

import pingpong.elements.PingPong
import pingpong.elements.Over
import pingpong.elements.Done
import pingpong.table.Table
import pingpong.player.Player

case class Umpire(name: String, players: List[Player], table: Table)
extends Worker[PingPong](table) {
override def toString = name

def work() = table.reg {
case Over =>
println(this + " done")
for { _ <- players } table.put(Done)
println(this + " stop")
}
}




Running the PingPongApp


Running the pingpong app produces something like.






ponger_1 pong
pinger_1 ping
ponger_2 pong
pinger_2 ping
ponger_1 pong
pinger_1 ping
ponger_2 pong
pinger_2 ping
ponger_1 pong
pinger_1 ping
ponger_2 pong
pinger_2 ping
ponger_1 pong
pinger_1 ping
ponger_2 pong
pinger_2 ping
ponger_1 pong
pinger_1 ping
ponger_2 pong
pinger_2 ping
ponger_1 pong
pinger_1 ping
ponger_2 pong
pinger_2 ping
ponger_1 pong
pinger_1 ping
ponger_2 pong
pinger_2 ping
ponger_1 pong
pinger_1 over
_umpire_ done
ponger_2 stop
pinger_2 stop
ponger_1 stop
_umpire_ stop
pinger_1 stop




DiningApp


We are ready for the second application DiningApp.
Details will be explained in what follows: for now, just admire it's simplicity.






package dining.globals

import scala.math.random
import scala.math.round
import dining.table.Table
import dining.elements.ChopStick
import dining.philosopher.Philosopher

object Globals {
val size = 5

val table = Table()
(1 to size).foreach(i => table.put(ChopStick(i)))

private def thinkTime = round(5000 * random)
private def eatTime = round(3000 * random)
private def delayTime = round(1000 * random)

val philosophers =
for (i <- 1 to size)
yield new Philosopher(i, thinkTime, eatTime, delayTime, table)

def startTime = round(1000 * random)
}

package apps

import dining.globals.Globals.philosophers
import dining.globals.Globals.startTime

object DiningApp {
def main(args: Array[String]): Unit = {
for (philosopher <- philosophers) {
Thread.sleep(startTime)
philosopher.work()
}
}
}




ChopStick


The case class ChopStick represents the data that drive the application.






package dining.elements

case class ChopStick(i: Int) {
override def toString = "cs" + i
}




Table


The case class Table represents the dining table.






package dining.table

import space.Space

import dining.elements.ChopStick

case class Table() extends Space[ChopStick]




Philosopher


The Philosopher case class represents a dining philosopher.
A philosopher can eat, work with a ChopStick(`left`) and a ChopStick(`right`).






package dining.philosopher

import worker.Worker

import dining.globals.Globals.size
import dining.table.Table
import dining.elements.ChopStick

class Philosopher(i: Int, thinkTime: Long, eatTime: Long, delayTime: Long, table: Table)
extends Worker[ChopStick](table) {
private val left = i
private val right = if (i != size) { i + 1 } else { (i + 1) % size }
private var hasLeft = false
private var hasRight = false

override def toString = {
var string = "ph" + i + "("
if (hasLeft) { string += "cs" + left }
string += ","
if (hasRight) { string += "cs" + right }
string += ")"
string
}

def work() = table.reg {
case ChopStick(`left`) => {
hasLeft = true
Thread.sleep(delayTime)
table.reg {
case ChopStick(`right`) => {
hasRight = true
println(this + " starts eating [ table = " + table + " ]")
Thread.sleep(eatTime)
println(this + " stops eating [ table = " + table + " ]")
table.put(ChopStick(left))
hasLeft = false
table.put(ChopStick(right))
hasRight = false
Thread.sleep(thinkTime)
work()
}
}
}
}
}




Running the DiningApp


Running the dining app produces something like.






ph1(cs1,cs2) starts eating [ table = (Queue(cs3, cs4, cs5)) ]
ph1(cs1,cs2) stops eating [ table = (Queue(cs3, cs4, cs5)) ]
ph3(cs3,cs4) starts eating [ table = (Queue(cs5, cs1)) ]
ph3(cs3,cs4) stops eating [ table = (Queue(cs1)) ]
ph2(cs2,cs3) starts eating [ table = (Queue(cs1)) ]
ph5(cs5,cs1) starts eating [ table = (Queue()) ]
ph2(cs2,cs3) stops eating [ table = (Queue()) ]
ph5(cs5,cs1) stops eating [ table = (Queue(cs2)) ]
ph4(cs4,cs5) starts eating [ table = (Queue(cs2)) ]
ph1(cs1,cs2) starts eating [ table = (Queue()) ]
ph1(cs1,cs2) stops eating [ table = (Queue()) ]
ph4(cs4,cs5) stops eating [ table = (Queue(cs1, cs2)) ]
ph3(cs3,cs4) starts eating [ table = (Queue(cs1, cs2, cs5)) ]
ph3(cs3,cs4) stops eating [ table = (Queue(cs1, cs5)) ]
ph2(cs2,cs3) starts eating [ table = (Queue(cs1, cs5)) ]
ph4(cs4,cs5) starts eating [ table = (Queue(cs1)) ]
ph2(cs2,cs3) stops eating [ table = (Queue()) ]
ph1(cs1,cs2) starts eating [ table = (Queue()) ]
ph4(cs4,cs5) stops eating [ table = (Queue()) ]
ph3(cs3,cs4) starts eating [ table = (Queue()) ]
ph1(cs1,cs2) stops eating [ table = (Queue()) ]
ph5(cs5,cs1) starts eating [ table = (Queue(cs2)) ]
ph3(cs3,cs4) stops eating [ table = (Queue(cs2)) ]
ph5(cs5,cs1) stops eating [ table = (Queue(cs2, cs3)) ]
ph4(cs4,cs5) starts eating [ table = (Queue(cs2, cs3, cs1)) ]
ph4(cs4,cs5) stops eating [ table = (Queue()) ]
ph3(cs3,cs4) starts eating [ table = (Queue(cs5)) ]
ph3(cs3,cs4) stops eating [ table = (Queue(cs5)) ]
ph2(cs2,cs3) starts eating [ table = (Queue(cs5, cs4)) ]
...





It is instructive to play around with delay, eat and think times.


















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$

Thursday, April 14, 2011

ScalaFp 03 (State)






Expect frequent changes.





State


Here is an aspect of computations: state.


Here is StateModule.
The abstract state methods are _get and _set.






package com.imaginej

package state

trait StateModule {
type S
type M[+Z] <: State[Z]
def _get: Unit => M[S]
def _set: S => M[Unit]
trait State[+A] { self: M[A] =>
}
}




StateMonads


The extra concrete state monad method is _do.






package com.imaginej

package monad

package state

import monad.MonadModule
import com.imaginej.state.StateModule

trait StateMonadModule
extends MonadModule
with StateModule {
def _do: (S => S) => M[Unit] =
f =>
for {
s <- _get(())
u <- _set(f(s))
} yield u
type M[+Z] <: StateMonad[Z]
trait StateMonad[+A]
extends Monad[A]
with State[A] { self: M[A] =>
}
}




Transformed Monads


Monads can be transformed.


Here is TransformedMonadModule.
It makes use of an implicit monadObject.
The abstract transformed monad method is _lift.
There are also abstract openT and _closeT methods.
The abstract method _return can now be defined.






package com.imaginej

package monad

package transformed

import monad.MonadModule

trait TransformedMonadModule
extends MonadModule {
type MonadModuleType <: MonadModule
implicit val monadObject: MonadModuleType
type FromM[+Z] = monadObject.M[Z]
type FromIn[Z] = monadObject.In[Z]
type FromOut[Z] = monadObject.Out[Z]
def _fromReturn[Z]: Z => FromM[Z] =
monadObject._return(_)
type M[+Z] <: TransformedMonadTrait[Z]
type ToM[+Z]
def _closeT[Z]: ToM[Z] => M[Z]
def _lift[Z]: FromM[Z] => ToM[Z]
def _liftT[Z] =
_lift[Z] andThen _closeT[Z]
override def _return[Z] =
z =>
_liftT {
_fromReturn(z)
}
trait TransformedMonadTrait[+A]
extends Monad[A] { self: M[A] =>
def openT: ToM[A]
}
}




State Transformed Monads


Here is StateTransformedMonadModule.
It makes use of a type ToM[+Z] = S => FromM[(Z, S)].
The abstract methods flatMap, _get, _set and _lift can now be defined.
Also a method runState is defined.






package com.imaginej

package monad

package state.transformed

import com.imaginej.monad.state.StateMonadModule
import com.imaginej.monad.transformed.TransformedMonadModule

trait StateTransformedMonadModule
extends TransformedMonadModule
with StateMonadModule {
type M[+Z] <: StateTransformedMonadTrait[Z]
type ToM[+Z] = S => FromM[(Z, S)]
type In[-Z] = S
override def _lift[Z] =
mz => s =>
mz flatMap { z =>
_fromReturn((z, s))
}
override def _get =
_ =>
_closeT { s =>
_fromReturn((s, s))
}
override def _set =
s =>
_closeT { _ =>
_fromReturn(((), s))
}
trait StateTransformedMonadTrait[+A]
extends TransformedMonadTrait[A]
with StateMonad[A] { self: M[A] =>
override def flatMap[B](a_f_mb: A => M[B]) =
_closeT { s =>
this.openT(s) flatMap {
case (a, s) =>
a_f_mb(a) openT s
}
}
def runState[B >: A](s: S)(i: FromIn[(B, S)]): FromOut[(B, S)] =
this openT s run i
}
}




State Transformed Monad Instances


Here is a state transformed monad instance.







StateTransformedIdentityMonad.






package com.imaginej

package monad

package state.instances

import monad.instances.IdentityMonadObject
import monad.state.transformed.StateTransformedMonadModule

abstract class StateTransformedIdentityMonadModule(
implicit override val monadObject: IdentityMonadObject.type )
extends StateTransformedMonadModule {
type MonadModuleType = IdentityMonadObject.type
type M[+Z] = StateTransformedIdentityMonad[Z]
type Out[+Z] = (Z, S)
def _closeT[Z] =
StateTransformedIdentityMonad[Z](_)
case class StateTransformedIdentityMonad[+A](
val openT: S => IdentityMonadObject.M[(A, S)])
extends StateTransformedMonadTrait[A] {
def run[B >: A](s: S): (B, S) =
runState(s) ()
}
}

import monad.MonadModule.identityMonad

object IntStateTransformedIdentityMonadObject
extends StateTransformedIdentityMonadModule {
type S = Int
}




Implicit State Transformed Monads


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






import instances.IntStateTransformedIdentityMonadObject

object StateMonadModule {
implicit def intStateTransformedIdentityMonadObject =
IntStateTransformedIdentityMonadObject
}




Application


Here is an application.






package com.imaginej

package apps

import monad.state.instances._

object UsingStateMonads {
def usingStateTransformedIdentityMonad() {
import IntStateTransformedIdentityMonadObject._
val computation1 =
for {
s <- _get(())
_ <- _do(_ + 1)
} yield s + 1
println {
computation1 run 0
}
val computation2 =
for {
_ <- _do(_ + 1)
s <- _get(())
} yield s + 1
println {
computation2 run 0
}
}
def main(args: Array[String]) {
usingStateTransformedIdentityMonad()
}
}





Running the application yields.




$ scala com.imaginej.apps.UsingStateMonads
(1,1)
(2,1)




Transformed ChoiceMonads


Choice monads can be transformed.


Here is TransformedChoiceMonadModule.
The abstract method _nothing can now be defined.






package com.imaginej

package monad

package choice

package transformed

import monad.choice.ChoiceMonadModule
import monad.transformed.TransformedMonadModule

trait TransformedChoiceMonadModule
extends TransformedMonadModule
with ChoiceMonadModule {
override type MonadModuleType <: ChoiceMonadModule
def _fromNothing[Z]: FromM[Z] =
monadObject._nothing
override def _nothing[Z] =
_liftT {
_fromNothing
}
type M[+Z] <: TransformedChoiceMonadTrait[Z]
trait TransformedChoiceMonadTrait[+A]
extends TransformedMonadTrait[A]
with ChoiceMonad[A] { self: M[A] =>
}




State Transformed Choice Monads


Here isStateTransformedChoiceMonadModule.
The abstract method or can now be defined.






package com.imaginej

package monad

package state.transformed

import monad.state.StateMonadModule
import monad.choice.transformed.TransformedChoiceMonadModule

trait StateTransformedChoiceMonadModule
extends TransformedChoiceMonadModule
with StateTransformedMonadModule {
type M[+Z] <: StateTransformedChoiceMonadTrait[Z]
trait StateTransformedChoiceMonadTrait[+A]
extends TransformedChoiceMonadTrait[A]
with StateTransformedMonadTrait[A] { self: M[A] =>
override def or[B >: A](mb: => M[B]): M[B] =
_closeT { s =>
this.openT(s) or mb.openT(s)
}
}
}




State Transformed Choice Monad Instances


Here are some state transformed choice monad instances.







StateTransformedTraversableChoiceMonadModule.






package com.imaginej

package monad

package choice

package state.instances

import instances.TraversableChoiceMonadObject
import monad.state.transformed.StateTransformedChoiceMonadModule

abstract class StateTransformedTraversableChoiceMonadModule(
implicit override val monadObject: TraversableChoiceMonadObject.type )
extends StateTransformedChoiceMonadModule {
type MonadModuleType = TraversableChoiceMonadObject.type
type M[+Z] = StateTransformedTraversableChoiceMonad[Z]
type Out[+Z] = Traversable[(Z, S)]
def _closeT[Z] =
StateTransformedTraversableChoiceMonad[Z](_)
case class StateTransformedTraversableChoiceMonad[+A](
val openT: S => TraversableChoiceMonadObject.M[(A, S)])
extends StateTransformedChoiceMonadTrait[A] {
def run[B >: A](s: S): Traversable[(B, S)] =
runState(s) ()
}
}

import monad.choice.ChoiceMonadModule.traversableChoiceMonad

object IntStateTransformedTraversableChoiceMonadObject
extends StateTransformedTraversableChoiceMonadModule {
type S = Int
}





StateTransformedOptionChoiceMonadModule.






package com.imaginej

package monad

package choice

package state.instances

import instances.OptionChoiceMonadObject
import monad.state.transformed.StateTransformedChoiceMonadModule

abstract class StateTransformedOptionChoiceMonadModule(
implicit override val monadObject: OptionChoiceMonadObject.type )
extends StateTransformedChoiceMonadModule {
type MonadModuleType = OptionChoiceMonadObject.type
type M[+Z] = StateTransformedOptionChoiceMonad[Z]
type Out[+Z] = Option[(Z, S)]
def _closeT[Z] =
StateTransformedOptionChoiceMonad[Z](_)
case class StateTransformedOptionChoiceMonad[+A](
val openT: S => OptionChoiceMonadObject.M[(A, S)])
extends StateTransformedChoiceMonadTrait[A] {
def run[B >: A](s: S): Option[(B, S)] =
runState(s) ()
}
}

import monad.choice.ChoiceMonadModule.optionChoiceMonad

object IntStateTransformedOptionChoiceMonadObject
extends StateTransformedOptionChoiceMonadModule {
type S = Int
}




Implicit State Transformed Choice Monads


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






import instances.IntStateTransformedIdentityMonadObject
import monad.choice.state.instances.IntStateTransformedTraversableChoiceMonadObject
import monad.choice.state.instances.IntStateTransformedOptionChoiceMonadObject

object StateMonadModule {
implicit def intStateTransformedIdentityMonadObject =
IntStateTransformedIdentityMonadObject
implicit def intStateTransformedTraversableChoiceMonadObject =
IntStateTransformedTraversableChoiceMonadObject
implicit def intStateTransformedOptionChoiceMonadObject =
IntStateTransformedOptionChoiceMonadObject
}




Application


Here is an application.






package com.imaginej

package apps

import monad.choice.state.instances._

object UsingStateAndChoiceMonads {
def usingStateTransformedOptionChoiceMonad() {
import IntStateTransformedOptionChoiceMonadObject._
val computation1 =
_nothing or {
for {
_ <- _do(_ + 1)
s <- _get(())
} yield s
}
println {
computation1 run 0
}
val computation2 =
_nothing or {
for {
s <- _get(())
_ <- _do(_ + 1)
} yield s
}
println {
computation2 run 0
}
}
def usingStateTransformedTraversableChoiceMonad1() {
import IntStateTransformedTraversableChoiceMonadObject._
val computation1 =
_nothing or {
for {
_ <- _do(_ + 1)
s <- _get(())
} yield s
}
println {
computation1 run 0
}
val computation2 =
_nothing or {
for {
s <- _get(())
_ <- _do(_ + 1)
} yield s
}
println {
computation2 run 0
}
}
def usingStateTransformedTraversableChoiceMonad2() {
import IntStateTransformedTraversableChoiceMonadObject._
val computation1 =
for {
s <- _get(())
} yield s
val computation2 =
for {
s <- _get(())
} yield s + 1
val computation =
computation1 or computation2
println {
computation run 0
}
}
def usingStateTransformedTraversableChoiceMonad3() {
import IntStateTransformedTraversableChoiceMonadObject._
val computation1 =
for {
s <- _get(())
} yield (s + 1)
val computation2 =
for {
_ <- _do(_ + 1)
_ <- _do(_ + 1)
s <- _get(())
} yield (s + 1)
val computation =
computation1 or computation2
println {
computation run 0
}
}
def main(args: Array[String]) {
usingStateTransformedOptionChoiceMonad()
usingStateTransformedTraversableChoiceMonad1()
usingStateTransformedTraversableChoiceMonad2()
usingStateTransformedTraversableChoiceMonad3()
}
}





Running the application yields.




$ scala com.imaginej.apps.UsingStateAndChoiceMonads
Some((1,1))
Some((0,1))
List((1,1))
List((0,1))
List((0,0), (1,0))
List((1,0), (3,2))

ScalaFp 02 (Choice)






Expect frequent changes.





Choice


Here is an of apect of computations: choice.


Here is ChoiceModule.
The abstract choice methods are _nothing and or.






package com.imaginej

package choice

trait ChoiceModule {
type M[+Z] <: Choice[Z]
def _nothing[Z]: M[Z]
trait Choice[+A] { self: M[A] =>
def or[B >: A](mb: => M[B]): M[B]
}
}




ChoiceMonads


The extra concrete choice monad method is withFilter.






package com.imaginej

package monad

package choice

import monad.MonadModule
import com.imaginej.choice.ChoiceModule

trait ChoiceMonadModule
extends MonadModule
with ChoiceModule {
type M[+Z] <: ChoiceMonad[Z]
trait ChoiceMonad[+A]
extends Monad[A]
with Choice[A] { self: M[A] =>
def withFilter(ap: A => Boolean) =
flatMap { a =>
if (ap(a)) {
_return(a)
} else {
_nothing
}
}
}
}




ChoiceMonad Instances


Here are some choice monad instances.







TraversableChoiceMonad.






package com.imaginej

package monad

package choice

package instances

import monad.choice.ChoiceMonadModule

object TraversableChoiceMonadObject
extends ChoiceMonadModule {
type M[+Z] = TraversableChoiceMonad[Z]
type In[-Z] = Unit
type Out[+Z] = Traversable[Z]
override def _return[Z] =
z => TraversableChoiceMonad(Traversable(z))
override def _nothing[Z] =
new TraversableChoiceMonad(Traversable())
def _close[Z]: Traversable[Z] => M[Z] =
TraversableChoiceMonad(_)
case class TraversableChoiceMonad[+A](val open: Traversable[A])
extends ChoiceMonad[A] {
override def run[B >: A](u: Unit): Traversable[B] =
this.open
override def flatMap[B](a_f_mb: A => M[B]): M[B] =
_close(for {
a <- this.open
b <- a_f_mb(a).open
} yield b)
override def or[B >: A](mb: => M[B]) =
_close(this.open ++ mb.open)
}
}





OptionChoiceMonad.




Note: options are not traversable, but we make them traversable
using an implicit conversion.






package com.imaginej

package monad

package choice

package instances

import monad.choice.ChoiceMonadModule

object OptionChoiceMonadObject
extends ChoiceMonadModule {
type M[+Z] = OptionChoiceMonad[Z]
type In[-Z] = Unit
type Out[+Z] = Option[Z]
override def _return[Z] =
z => OptionChoiceMonad(Some(z))
override def _nothing[Z] =
OptionChoiceMonad(None)
def _close[Z]: Option[Z] => M[Z] =
OptionChoiceMonad(_)
implicit def _ocm_f_tcm[Z]: M[Z] => TraversableChoiceMonadObject.M[Z] =
mz => TraversableChoiceMonadObject._close(mz.open)
case class OptionChoiceMonad[+A](val open: Option[A])
extends ChoiceMonad[A] {
override def run[B >: A](u: Unit): Option[B] =
this.open
override def flatMap[B](a_f_mb: A => M[B]): M[B] =
_close(for {
a <- this.open
b <- a_f_mb(a).open
} yield b)
override def or[B >: A](mb: => M[B]) =
_close(this.open orElse mb.open)
}
}




Implicit Choice Monads


It is convenient to define implicit choice monads for later usage.






import instances.TraversableChoiceMonadObject
import instances.OptionChoiceMonadObject

object ChoiceMonadModule {
implicit val traversableChoiceMonad =
TraversableChoiceMonadObject
implicit val optionChoiceMonad =
OptionChoiceMonadObject
}




Application


Here is an application.






package com.imaginej

package apps

import monad.choice.instances._

object UsingChoiceMonads {
def usingTraversableChoiceMonad() {
import TraversableChoiceMonadObject._
val computation =
for {
x <- _close(List(1, 2))
y <- _close(List(x + 1, x + 2))
if (x == y)
} yield (x, y)
println {
computation run ()
}
}
def usingOptionChoiceMonad() {
import OptionChoiceMonadObject._
val computation =
for {
x <- _close(Some(1))
y <- _close(Some(x + 1))
if (y >= 2)
} yield (x, y)
println {
computation run ()
}
}
def usingTwoChoiceMonads() {
import TraversableChoiceMonadObject.{ _close => _closeT, _ }
import OptionChoiceMonadObject.{ _close => _closeO, _ }
val maybeInts =
_closeT(List(_closeO(Some(1)), _closeO(None), _closeO(Some(2))))
val computation =
for {
maybeInt <- maybeInts
i <- maybeInt
if (i >= 2)
} yield i
println {
computation run ()
}
}
def main(args: Array[String]) {
usingTraversableChoiceMonad()
usingOptionChoiceMonad()
usingTwoChoiceMonads()
}
}





Running the application yields.




$ scala com.imaginej.apps.UsingChoiceMonads
List()
Some((1,2))
List(2)

Saturday, April 9, 2011

ScalaFp 01 (Monads)






Expect frequent changes.





Computations


The idea behind the ScalaFp library is to model aspects of computations in a functional way.


Here is ComputationModule.
The abtract computation method is run.
run is Computation functionality.


Note: Module scope type parameters are called Z, Y, X ... .


Note: Other type parameters are called A, B, C ... .








package com.imaginej

package computation

trait ComputationModule {
type M[+Z] <: Computation[Z]
type In[-Z]
type Out[+Z]
trait Computation[+A] { self: M[A] =>
def run[B >: A](i: In[B]): Out[B]
}
}




Monads


It is generally accepted that monads are convenient for modeling aspects of computations.
Here is MonadModule.
The abstract monad methods are _return and flatMap.
_return is MonadModule functionality.
flatMap is Monad functionality.


Note: Module functionality names will systematically start with an underscore.


The extra concrete monad methods are _join, >=, >> and map .






package com.imaginej

package monad

import computation.ComputationModule

trait MonadModule
extends ComputationModule {
type M[+Z] <: Monad[Z]
def _return[Z]: Z => M[Z]
def _join[Z]: M[M[Z]] => M[Z] =
_.flatMap(identity)
trait Monad[+A]
extends Computation[A] { self: M[A] =>
def flatMap[B](a_f_mb: A => M[B]): M[B]
def >=[B](a_f_mb: A => M[B]): M[B] =
flatMap(a_f_mb)
def >>[B](mb: => M[B]): M[B] =
this flatMap { _ => mb }
def map[B](afb: A => B) =
this flatMap (afb andThen _return)
}
}




Monad Instances


Here are some monad instances.







IdentityMonad.






package com.imaginej

package monad

package instances

import monad.MonadModule

object IdentityMonadObject
extends MonadModule {
type M[+Z] = IdentityMonad[Z]
type In[-Z] = Unit
type Out[+Z] = Z
override def _return[Z] =
IdentityMonad[Z](_)
def _close[Z]: Z => M[Z] =
IdentityMonad[Z](_)
case class IdentityMonad[+A](val open: A)
extends Monad[A] {
override def run[B >: A](u: Unit): B =
this.open
override def flatMap[B](a_f_mb: A => M[B]) =
a_f_mb(this.open)
}
}





TraversableMonad.






package com.imaginej

package monad

package instances

import monad.MonadModule

object TraversableMonadObject
extends MonadModule {
type M[+Z] = TraversableMonad[Z]
type In[-Z] = Unit
type Out[+Z] = Traversable[Z]
override def _return[Z] =
z => TraversableMonad(Traversable(z))
def _close[Z]: Traversable[Z] => M[Z] =
TraversableMonad(_)
case class TraversableMonad[+A](val open: Traversable[A])
extends Monad[A] {
override def run[B >: A](u: Unit): Traversable[B] =
this.open
override def flatMap[B](a_f_mb: A => M[B]) =
_close(
for {
a <- this.open
b <- a_f_mb(a).open
} yield b)
}
}





OptionMonad.




Note: options are not traversable, but we make them traversable
using an implicit conversion.






package com.imaginej

package monad

package instances

import monad.MonadModule

object OptionMonadObject
extends MonadModule {
type M[+Z] = OptionMonad[Z]
type In[-Z] = Unit
type Out[+Z] = Option[Z]
override def _return[Z] =
z => OptionMonad(Some(z))
def _close[Z]: Option[Z] => M[Z] =
OptionMonad(_)
implicit def _om_f_tm[Z]: M[Z] => TraversableMonadObject.M[Z] =
mz => TraversableMonadObject._close(mz.open)
case class OptionMonad[+A](val open: Option[A])
extends Monad[A] {
override def run[B >: A](u: Unit): Option[B] =
this.open
override def flatMap[B](a_f_mb: A => M[B]): M[B] =
_close(for {
a <- this.open
b <- a_f_mb(a).open
} yield b)
}
}




Implicit Monads


It is convenient to define implicit monads for later usage.






import instances.IdentityMonadObject
import instances.TraversableMonadObject
import instances.OptionMonadObject

object MonadModule {
implicit val identityMonad =
IdentityMonadObject
implicit val traversableMonad =
TraversableMonadObject
implicit val optionMonad =
OptionMonadObject
}




Application


Here is an application.






package com.imaginej

package apps

import monad.instances._

object UsingMonads {
def usingIdentityMonad() {
import IdentityMonadObject._
val computation =
for {
x <- _close(1)
y <- _close(x + 1)
} yield (x, y)
println {
computation run ()
}
}
def usingTraversableMonad() {
import TraversableMonadObject._
val computation1 =
for {
x <- _close(List(1, 2))
y <- _close(List(x + 1, x + 2))
} yield (x, y)
println {
computation1 run ()
}
val computation2 =
for {
x <- _close(List(1, 2))
y <- _close(List())
} yield (x, y)
println {
computation2 run ()
}
}
def usingOptionMonad() {
import OptionMonadObject._
val computation1 =
for {
x <- _close(Some(1))
y <- _close(Some(x + 1))
} yield (x, y)
println {
computation1 run ()
}
val computation2 =
for {
x <- _close(Some(1))
y <- _close(None)
} yield (x, y)
println {
computation2 run ()
}
}
def usingTwoMonads() {
import TraversableMonadObject.{ _close => _closeT, _ }
import OptionMonadObject.{ _close => _closeO, _ }
val maybeInts =
_closeT(List(_closeO(Some(1)), _closeO(None), _closeO(Some(2))))
val computation =
for {
maybeInt <- maybeInts
i <- maybeInt
} yield i
println {
computation run ()
}
}
def main(args: Array[String]) {
usingIdentityMonad()
usingTraversableMonad()
usingOptionMonad()
usingTwoMonads()
}
}





Running the application yields.




$ scala com.imaginej.apps.UsingMonads
(1,2)
List((1,2), (1,3), (2,3), (2,4))
List()
Some((1,2))
None
List(1, 2)

ScalaFp 00 (Logo)




This is the first of a series of blogs on a library, called ScalaFp, that I develop in my spare time.





Expect frequent changes.





Here is the ScalaFp logo.






____________________________________________________________________________________
/ ___ _________ /\
/ / /\ / ______/\ / /
/ _________ _________ _________ / / /_________ / /\_____\/________ / /
/ / ______/\ / ______/\ /_____ /\ / / //_____ /\ / /_/__ / ___ /\ / /
/ / /_____ \// /\_____\/_\____/ / // / /_\____/ / / / ____/\ / /__/ / / / /
/ /_____ /\ / / / / ___ / // / // ___ / / / /\____\/ / _____/ / / /
/ _______/ / // /_/___ / /__/ / // / // /__/ / / / / / / /\____\/ / /
/ /________/ //________/\ /________/ //__/ //________/ / /__/ / /__/ / / /
/ \________\/ \________\/ \________\/ \__\/ \________\/ \__\/ \__\/ v1.0 / /
/ / /
/ Scala Functional Programming Library / /
/ author Luc Duponcheel 2009-2011 / /
/___________________________________________________________________________________/ /
\___________________________________________________________________________________\/