WebAssembly es un lenguaje de bajo nivel, similar a ensamblador, diseñado para ser rápido de cargar y ejecutar en navegadores modernos. Su objetivo es permitir que aplicaciones escritas en distintos lenguajes se ejecuten en la web con velocidad casi nativa.
Los formatos que soporta son:
- .wasm: un formato binario ejecutable.
- .wat: un formato formato de texto legible.
Se complementa con JavaScript; permite invocar funciones WASM desde JS y viceversa.
¿Cuál es el objetivo de WebAssembly?
El objetivo de WebAssembly es compilar código escrito en lenguajes como Rust, C o C++ (entre otros) y transformarlo en un módulo .wasm que puede ejecutarse en navegadores o en entornos como Node.js con rendimiento cercano al nativo.
Flujo típico de trabajo con WebAssembly
- Escribimos nuestro código en un lenguaje soportado (ej. Rust, C, C++, Go, AssemblyScript).
- Compilamos ese código a WebAssembly y se generará un archivo .wasm.
- Cargamos el módulo en tu aplicación web usando JavaScript.
- Ejecutamos las funciones exportadas desde el módulo .wasm como si fueran algo nativo.
¿Y qué con Haskell?
Existen dos alternativas en Haskell para hacer esto:
- Mediante las herramientas wasm32-wasi-ghc y wasm32-wasi-cabal.
- Mediante Asterius (aunque ya se encuentra deprecado).
Usaremos Cabal para crear el código WASM.
1. Crearemos un directorio donde alojar nuestro proyecto Cabal:
$ mkdir demo-cabal-wasm $ demo-cabal-wasm
2. Creamos el proyecto Cabal:
$ cabal init --non-interactive --package-name=hola-wasm --exe --main-is=Main.hs
La estructura del proyecto será la siguiente:
hola-wasm/ ├─ app/ │ └─ Main.hs ├─ hola-wasm.cabal └─ cabal.project
El código del programa ``Main.hs`` será el siguiente:
module Main where main :: IO () main = putStrLn "Hola, mundo desde Haskell en WebAssembly!"
3. Editamos el archivo ``hola-wasm.cabal``:
cabal-version: >=1.10 name: hola-wasm version: 0.1.0.0 build-type: Simple executable hola-wasm main-is: Main.hs build-depends: base >=4.14 && <4.20 default-language: Haskell2010
4. Compilamos a WebAssembly:
$ cabal build --with-compiler=ghc --ghc-options="--target=wasm32-wasi"
5. Si todo va bien, deberá generar un código .wasm. Ahora tendremos que crear un archivo ``main.js`` para incocar el código generado en el .wasm.
async function runWasm() { const response = await fetch("hola-wasm.wasm"); const bytes = await response.arrayBuffer(); const result = await WebAssembly.instantiate(bytes, { wasi_snapshot_preview1: { fd_write: (fd, iovs, iovs_len, nwritten, mem) => { console.log("Salida desde WASM (stdout simulado)"); return 0; } } }); } runWasm();
6. Crear una página HTML donde le incrustamos ese código JS.
<!DOCTYPE html> <html lang="es"> <head> <meta charset="UTF-8"> <title>Hola Haskell WASM</title> </head> <body> <h1>Ejemplo Haskell + WebAssembly</h1> <pre id="output"></pre> <script src="main.js"></script> </body> </html>
Ejecutamos con Python:
$ python -m http.server 8000
Abrimos el navegador en la ruta: http://localhost:8000
¡Hemos trabajado con WebAssembly desde Cabal!
Continuaremos con este tema en próximas entregas.
Enlaces:
https://alquimistadecodigo.blogspot.com/2026/04/webassembly-con-rust.htmlhttps://webassembly.org/
https://asterius.netlify.app/
https://ghc.gitlab.haskell.org/ghc/doc/users_guide/wasm.html
https://www.tushar-adhatrao.in/blogs/haskell_to_wasm.html
