Skip to content

Instantly share code, notes, and snippets.

@davegurnell
Created September 14, 2016 14:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save davegurnell/5211822f72db2541c2bec3747134c824 to your computer and use it in GitHub Desktop.
Save davegurnell/5211822f72db2541c2bec3747134c824 to your computer and use it in GitHub Desktop.
#!/usr/bin/env amm
load.ivy("org.typelevel" %% "cats" % "0.7.0")
@
import cats.{Id, ~>}
import cats.data.State
import cats.free._
import cats.free.Free._
import scala.collection.mutable
type NoteId = Int
type Time = Int
type Pitch = Int
type Duration = Int
sealed trait Command[A]
case class On(pitch: Pitch) extends Command[Int]
case class Off(id: Int) extends Command[Unit]
case object Chill extends Command[Unit]
def on(pitch: Pitch): Free[Command, Int] =
Free.liftF[Command, Int](On(pitch))
def off(id: Int): Free[Command, Unit] =
Free.liftF[Command, Unit](Off(id))
def chill: Free[Command, Unit] =
Free.liftF[Command, Unit](Chill)
val program = for {
a <- on(10)
_ <- chill
b <- on(20)
_ <- chill
c <- on(30)
_ <- chill
_ <- off(a)
_ <- off(b)
_ <- chill
_ <- chill
_ <- off(c)
} yield ()
case class PlayerState(nextId: NoteId = 0, playing: Map[NoteId, Pitch] = Map.empty, output: List[List[Pitch]] = Nil)
type Output[A] = State[PlayerState, A]
object TestInterpreter extends (Command ~> Output) {
def apply[A](cmd: Command[A]): Output[A] = cmd match {
case On(pitch) =>
State { state =>
val id = state.nextId
val newState = state.copy(state.nextId + 1, state.playing + (id -> pitch))
(newState, id)
}
case Off(id) =>
State.modify(state => state.copy(playing = state.playing - id))
case Chill =>
State.modify(state => state.copy(output = state.output :+ state.playing.values.toList.sorted))
}
}
val endState = program.foldMap(TestInterpreter).runS(PlayerState()).value
println(endState)
endState.output.foreach(println)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment