Translate

miércoles, 18 de febrero de 2026

Controlando los Efectos Colaterales: Elm, Akka y Koka


Los efectos colaterales son inevitables en cualquier programa real. Tarde o temprano necesitamos leer datos, escribir en pantalla, hacer una petición HTTP o guardar algo en una base de datos.

El problema no está en tener efectos, sino en no saber dónde y cuándo ocurren.


Lenguajes y frameworks como Elm, Akka y Koka proponen tres enfoques distintos para enfrentar este desafío, pero todos comparten la misma filosofía:

Mantener la lógica pura y controlada, y ejecutar los efectos en un punto bien definido.


Elm es un lenguaje funcional puro que se ejecuta en el navegador. En Elm, ninguna función puede tener efectos secundarios directamente.

En su lugar, el programa describe qué debería pasar, y el runtime de Elm se encarga de hacerlo realidad.


Por ejemplo, el corazón de un programa Elm suele tener esta función:


update : Msg -> Model -> (Model, Cmd Msg)


Cuando el usuario genera un mensaje (Msg), la función update:

  • recibe el estado actual (Model),
  • devuelve un nuevo modelo,
  • y opcionalmente un comando (Cmd Msg), que describe un efecto.


El punto clave es que update no ejecuta el efecto; simplemente lo describe.

Es el runtime de Elm quien decide cuándo y cómo hacerlo.

Así, todo el código de tu aplicación es puro y determinista, y los efectos están completamente bajo control.


Un ejemplo simple:


update msg model =

    case msg of

        LoadData ->

            ( model, Http.get { url = "/data", expect = GotData } )


        GotData response ->

            ( { model | data = response }, Cmd.none )


Aquí, LoadData devuelve una descripción de un efecto HTTP, pero Elm no lo ejecuta directamente.

La ejecución real ocurre más tarde, en un punto centralizado del runtime.


Akka, en el mundo de Scala y Java, aplica un principio muy similar desde la programación concurrente.

En Akka, los actores son unidades independientes que:

  • procesan un mensaje a la vez,
  • mantienen su propio estado interno,
  • y pueden enviar mensajes a otros actores.


Cada actor es como una pequeña cápsula que contiene su estado y sus efectos.

Nada del mundo exterior puede acceder a su estado directamente; solo se comunica mediante mensajes.


Por ejemplo:


class Counter extends Actor {

  var count = 0


  def receive: Receive = {

    case "inc" =>

      count += 1

      sender() ! count

  }

}


Este actor mantiene su propio contador y solo responde a mensajes.

El efecto (enviar una respuesta, escribir logs, actualizar estado) está encapsulado dentro del actor.


El runtime de Akka —el ActorSystem— se encarga de distribuir los mensajes y ejecutar los efectos concurrentemente, garantizando aislamiento y seguridad.

Desde afuera, un actor parece una función pura: recibe un mensaje y devuelve una respuesta.

Pero los efectos reales ocurren dentro del sistema, no en tu código.


Koka lleva la idea aún más lejos.

En lugar de confiar en un runtime que ejecuta los efectos, Koka los modela en el sistema de tipos.

Cada función en Koka declara explícitamente qué efectos puede producir.

Por ejemplo:


fun add(x : int, y : int) : int {

  x + y

}


Esta función es completamente pura.

En cambio:


fun printAdd(x : int, y : int) : <io> int {

  println("Sumando...")

  x + y

}


Aquí, el tipo <io> indica que esta función puede realizar operaciones de entrada/salida.

Koka rastrea los efectos de manera estática: el compilador sabe exactamente qué partes del programa son puras y cuáles no.


Esto permite escribir programas donde los efectos son explícitos, controlados y predecibles.

No hace falta leer todo el código para saber si una función puede modificar el mundo: el tipo te lo dice.


Aunque Elm, Akka y Koka se desarrollan en contextos muy diferentes —frontend funcional, backend concurrente y teoría de tipos—, los tres comparten una visión profunda de la pureza y el control de efectos.

  • Elm describe los efectos y delega su ejecución al runtime.
  • Akka encapsula los efectos en actores que procesan mensajes de forma aislada.
  • Koka anota los efectos en los tipos, haciéndolos explícitos desde el nivel más básico del lenguaje.


En los tres casos, la meta es la misma: escribir código predecible, testeable y sin sorpresas.