Howto: debugger Haskell (hdb) en Doom Emacs paso a paso
Para quien es esto
Quieres pausar codigo Haskell en Doom Emacs, ver tus thunks expandirse en vivo en el panel de variables, y hacer step over en una expresion perezosa. Esta guia te lleva del cero a tu primer breakpoint.
Si quieres entender POR QUE esto importa o leer el diario de batalla con todas las trampas, mira mi otro post: Hito doble: Haskell con debugger en Doom y en IntelliJ.
Aqui solo pasos.
Requisitos
- NixOS (o un sistema con
nixdisponible). Si estas en Ubuntu/ Mac/Windows, los pasos sirven, solo cambia la activacion del toolchain. - Doom Emacs instalado y funcionando.
- Un proyecto Haskell con
flake.nixycabal. Si no tienes uno, te sirve pensando-en-haskell como arranque. - Conexion a internet la primera vez (cabal descarga
haskell-debugger).
Paso 1: GHC 9.14 disponible en el proyecto
hdb requiere GHC 9.14 o superior. En tu
flake.nix:
{
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
outputs = { nixpkgs, ... }:
let
pkgs = import nixpkgs { system = "x86_64-linux"; };
in {
devShells.x86_64-linux.default = pkgs.mkShell {
buildInputs = [
pkgs.haskell.compiler.ghc914
pkgs.cabal-install
];
};
};
}Verifica entrando al shell:
cd ~/src/tu-proyecto-haskell
nix develop
ghc --version # debe mostrar 9.14.xPaso 2: Instalar hdb (haskell-debugger)
Dentro del nix develop:
cabal update
cabal install haskell-debugger --installdir=$HOME/.local/binEsto compila hdb y deja el binario en
~/.local/bin/hdb. Tarda unos minutos la
primera vez.
Verifica:
which hdb # /home/tu-usuario/.local/bin/hdb
hdb --versionPaso 3: Wrapper hdb-dap
Cuando un editor (Doom, IntelliJ) lanza hdb, no hereda el shell de nix develop. Sin GHC 9.14 en PATH, hdb aborta. El wrapper resuelve esto entrando en
nix develop antes de ejecutar.
Crea ~/.local/bin/hdb-dap:
#!/usr/bin/env bash
set -euo pipefail
# Sube buscando flake.nix
find_flake_root() {
local dir
dir="$(pwd)"
while [ "$dir" != "/" ]; do
if [ -f "$dir/flake.nix" ]; then
echo "$dir"; return 0
fi
dir="$(dirname "$dir")"
done
return 1
}
flake_root="$(find_flake_root || true)"
if [ -z "$flake_root" ]; then
echo "[hdb-dap] no flake.nix encontrado desde $(pwd)" >&2
exit 1
fi
cd "$flake_root"
# Ruta absoluta a hdb. nix develop NO incluye ~/.local/bin en PATH.
HDB_BIN="${HDB_BIN:-$HOME/.local/bin/hdb}"
if [ ! -x "$HDB_BIN" ]; then
echo "[hdb-dap] $HDB_BIN no encontrado" >&2
exit 1
fi
exec nix develop --command "$HDB_BIN" "$@"Hazlo ejecutable:
chmod +x ~/.local/bin/hdb-dapTest:
cd ~/src/tu-proyecto-haskell
hdb-dap server --port 19999 &
sleep 25 # primer arranque tarda
ss -tlnp | grep 19999 # debe estar listening
kill %1Paso 4: hie.yaml
Dile a hdb que tu fichero pertenece al
target del proyecto. Crea o edita hie.yaml
en la raiz:
cradle:
cabal:
- path: "./src"
component: "lib:tu-proyecto"
- path: "./app/Main.hs"
component: "tu-proyecto:exe:tu-exe"Adapta los componentes a tu .cabal. Si
no tienes hie.yaml, hdb falla con "Multi Cradle: No prefixes
matched".
Paso 5: Configurar dape en Doom
Doom no trae dape por defecto. Edita
~/.config/doom/packages.el:
(package! dape)Edita ~/.config/doom/config.el y
añade:
(after! flycheck
(add-to-list 'flycheck-disabled-checkers 'haskell-stack-ghc))
(use-package! dape
:config
;; hdb tarda ~20s descubriendo flags el primer launch
(setq dape-request-timeout 60)
(add-to-list 'dape-configs
`(haskell-hdb
modes (haskell-mode haskell-ts-mode haskell-cabal-mode)
ensure (lambda (config)
(unless (executable-find "hdb-dap")
(user-error "hdb-dap no encontrado en PATH")))
fn (dape-config-autoport)
host "localhost"
port :autoport
command "hdb-dap"
command-args ("server" "--port" :autoport)
:type "haskell-debugger"
:request "launch"
:projectRoot dape-cwd-fn
:entryFile dape-buffer-default
:entryPoint "main"
:entryArgs []
:extraGhcArgs []
:internalInterpreter t)))Ejecuta doom sync y reinicia Emacs.
Paso 6: Tu primer breakpoint
- Abre cualquier
.hsdentro del proyecto Haskell. - Verifica que
haskell-modeesta activo (mode-linelo muestra). - Coloca el cursor en una linea con expresion (un
let, undo, una llamada a funcion). Pulsa F9 para poner breakpoint. Sale bola roja en el margen. - Pulsa espacio-d-d (
SPC d d, comandodape) y seleccionahaskell-hdben el menu. - Espera 15-25 segundos.
hdbcompila el modulo dentro del flake y conecta. - Cuando para en el breakpoint, abre el panel de variables con
SPC d v. Veras los valores locales y los modulos.
Paso 7: Ver un thunk en vivo
En el panel de variables, busca una expresion que sepas que es perezosa. Por ejemplo, si tienes:
main = do
let xs = take 5 (map (^2) (filter even [1..1000000]))
print xsPon breakpoint en la linea let xs = .... Cuando para, en el panel veras
xs como <thunk> o con un guion bajo (depende del
bridge DAP de tu version).
Pulsa F10 (step over). Cuando
llegue al print xs, esa linea fuerza la
evaluacion. Vuelve a inspeccionar xs y
ahora sera [4,16,36,64,100]. Acabas de ver
lazy evaluation en vivo.
Atajos de teclado utiles
| Atajo | Comando dape | Que hace |
|---|---|---|
F5 |
dape-restart |
Reinicia la sesion |
F9 |
dape-breakpoint-toggle |
Pon/quita breakpoint |
F10 |
dape-next |
Step over (siguiente linea) |
F11 |
dape-step-in |
Step in (entra en funcion) |
F12 |
dape-step-out |
Step out (sale a la llamada) |
SPC d d |
dape |
Arranca debugger |
SPC d k |
dape-disconnect |
Cierra sesion |
SPC d v |
dape-info |
Panel info (Variables) |
SPC d e |
dape-evaluate-expression |
Evaluar expresion |
Lo que no esperar
- HLS no funciona con GHC 9.14
todavia. El
haskell-language- serveraun no soporta esta version. Si lo tenias activo, lo pierdes. Volvera cuando los maintainers actualicen. - Cada arranque recompila. Es
inherente a hdb (necesita el bytecode interpreter de GHC). 15-25s por
sesion. Para iterar, deja la sesion abierta y usa
dape-evaluate-expressiono el REPL embebido en lugar de cerrar y abrir.
Cierre
Con esto ya puedes pausar codigo Haskell, inspeccionar thunks y hacer stepping. La intuicion de lazy evaluation que antes solo se ganaba leyendo libros, ahora se ve en pantalla.
El howto equivalente para IntelliJ
Ultimate esta aqui: Howto
IntelliJ + LSP4IJ + hdb.
Comentarios (0)
Sin comentarios todavia. Se el primero!
Deja un comentario