Skip to content

Instantly share code, notes, and snippets.

@stew
Created May 8, 2014 12:27
Show Gist options
  • Save stew/3068690e0e97b037d71a to your computer and use it in GitHub Desktop.
Save stew/3068690e0e97b037d71a to your computer and use it in GitHub Desktop.
import scalaz._
import scalaz.std.list._
import scalaz.syntax.traverse._
import scalaz.State._
trait Main {
type TypeEnvironment
case class GetTypeEnvironment(get: TypeEnvironment)
case class Processor(after: GetTypeEnvironment)
def performTypeInference(typeEnv: TypeEnvironment, next: Processor): Processor
// STEW: original code, hard to read, seems too complicated
private def pipelineChildren(typeEnvironment: TypeEnvironment, children: List[Processor]): (TypeEnvironment, List[Processor]) = {
// Apply map by folding left with the new type environment
val stateTuple@(newTypeEnvironment, newChildren) = children.foldLeft((typeEnvironment, List[Processor]()))({
case (((typeEnv), previous), next) =>
val mappedProcessor = performTypeInference(typeEnv, next)
val newEnv = mappedProcessor.after.get
(newEnv, previous :+ mappedProcessor)
})
stateTuple
}
// STEW: rewrite as just tail recursion to see if it improves
// STEW: doesn't feel like much of an improvement, its perhaps more readable
def pipelineChildrenRecursive(typeEnv: TypeEnvironment, children: List[Processor]): (TypeEnvironment, List[Processor]) = {
def loop(typeEnv: TypeEnvironment, children: List[Processor], acc: List[Processor]): (TypeEnvironment, List[Processor]) = children match {
case Nil ⇒ (typeEnv, acc.reverse)
case x :: xs ⇒
val mappedProcessor = performTypeInference(typeEnv, x)
loop(mappedProcessor.after.get, xs, mappedProcessor :: acc)
}
loop(typeEnv, children, Nil)
}
// STEW: use State monad from scalaz, and this becomes much easier to read
def pipelineTraverse(p: Processor): State[TypeEnvironment, Processor] =
for {
env ← get[TypeEnvironment]
mapped = performTypeInference(env, p)
_ ← put(mapped.after.get)
} yield(mapped)
def pipelineChildrenWithStateMonad(typeEnv: TypeEnvironment,
children: List[Processor]): (TypeEnvironment, List[Processor]) =
children.traverseS(pipelineTraverse).run(typeEnv)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment