Created
May 8, 2014 12:27
-
-
Save stew/3068690e0e97b037d71a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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