scala dependency-injection functional-programming monads

scala - Uso de Reader Monad para inyección de dependencia



dependency-injection functional-programming (1)

La "mónada del lector" es solo la Function1 , por lo que todo lo que debe hacer es aceptar un argumento que contenga todas las cosas que necesita. Por ejemplo:

trait Config { def fly: FlyBehaviour def quack: QuackBehaviour } type Env[A] = Config => A

Ahora si quieres construir un Duck basado en este entorno:

val a: Env[Animal] = c => new Duck(c.fly, c.quack)

Y luego construir un Zoo basado en eso es fácil:

val z: Env[Zoo] = a andThen (new Zoo(_))

Utilizando Scalaz (o con un poco de trabajo por su cuenta) puede hacer uso de algunas sintaxis para "pedir" la configuración c :

val z: Env[Zoo] = for { c <- ask } yield new Zoo(Duck(c.fly, c.quack))

Recientemente vi las conversaciones Inyección de dependencia simple-muerta e inyección de dependencia sin gimnasia sobre DI con mónadas y me impresionó. Traté de aplicarlo en un problema simple, pero fallé tan pronto como se volvió no trivial. Realmente me gustaría ver una versión de inyección de dependencia en ejecución donde

  • Una clase que depende de más de un valor que debe inyectarse.
  • una clase que depende de una clase que depende de algo para ser inyectado

como en el siguiente ejemplo

trait FlyBehaviour { def fly() } trait QuackBehaviour { def quack() } trait Animal { def makeSound() } // needs two behaviours injected class Duck(val flyBehaviour: FlyBehaviour, val quackBehaviour: QuackBehaviour) extends Animal { def quack() = quackBehaviour.quack() def fly() = flyBehaviour.fly() def makeSound() = quack() } // needs an Animal injected (e.g. a Duck) class Zoo(val animal: Animal) // Spring for example would be able to provide a Zoo instance // assuming a Zoo in configured to get a Duck injected and // a Duck is configured to get impl. of FlyBehaviour and QuackBehaviour injected val zoo: Zoo = InjectionFramework.get("Zoo") zoo.animal.makeSound()

Sería muy útil ver una implementación de ejemplo utilizando el lector Monad, ya que siento que me falta un impulso en la dirección correcta.

¡Gracias!