debugging haskell ghci

debugging - Depuración de IO en un módulo de paquete dentro de GHCi



haskell (1)

Estoy haciendo IO de bajo nivel (para enlaces de biblioteca) en Haskell y estoy experimentando una falla de seguridad. Me gustaría usar GHCi''s : break para averiguar qué está pasando, pero esto es lo que sucede:

> import SDL > :break SDL.setPaletteColors cannot set breakpoint on setPaletteColors: module SDL.Video.Renderer is not interpreted

Dado que el código ofensivo no está dentro de mis propios módulos, sino dentro de un módulo en un paquete externo, se carga como código compilado y aparentemente no puedo usar : romper en los módulos compilados.

El manual de GHCi confirma esto y proporciona una pista:

Hay una restricción importante: los puntos de interrupción y los pasos únicos solo están disponibles en los módulos interpretados; El código compilado es invisible para el depurador [5].

[5] Tenga en cuenta que los paquetes solo contienen código compilado, por lo que la depuración de un paquete requiere encontrar su origen y cargarlo directamente.

Probémoslo directamente:

> :load some_path/sdl2/src/SDL/Video/Renderer.hs some_path/sdl2/src/SDL/Video/Renderer.hs:101:8: Could not find module ‘Control.Monad.IO.Class’ It is a member of the hidden package ‘transformers-0.3.0.0’. Perhaps you need to add ‘transformers’ to the build-depends in your .cabal file. Use -v to see a list of the files searched for.

Puedo agregar las dependencias a mi archivo .cabal, pero esto ya se siente mal. Una vez que he hecho eso:

> :load some_path/sdl2/src/SDL/Video/Renderer.hs some_path/sdl2/src/SDL/Video/Renderer.hs:119:8: Could not find module ‘SDL.Internal.Numbered’ it is a hidden module in the package ‘sdl2-2.0.0’ Use -v to see a list of the files searched for.

Podría hacer públicos esos módulos (probablemente? Modificando el paquete .cabal?), Pero en este punto parece una forma muy extraña de hacer las cosas y no lo seguí.

EDITAR:

En realidad lo intenté y obtuve el resultado desconcertante:

> :load some_path/sdl2/src/SDL/Video/Renderer.hs [1 of 1] Compiling SDL.Video.Renderer ( some_path/sdl2/src/SDL/Video/Renderer.hs, interpreted ) Ok, modules loaded: SDL.Video.Renderer. > :break SDL.setPaletteColors cannot set breakpoint on SDL.setPaletteColors: module SDL.Video.Renderer is not interpreted

Mi suposición (sin educación): es porque el módulo externo todavía está vinculado a mi código como un binario, y cargarlo dinámicamente en modo interpretado no cambia eso.

Entonces, para resumir la pregunta: ¿cuál es una buena manera de depurar IO en un paquete externo?

Notas adicionales:

  1. Tengo la fuente del paquete que necesito para depurar; de hecho, se ha agregado al proyecto con Cabal sandbox add-source

  2. Una opción alternativa al uso de GHCi sería agregar rastreos al origen del paquete, pero esta es una opción desafortunada, ya que implica la compilación del paquete en cada modificación (siempre que necesite más información sobre la ejecución y modificar los rastreos), y eso Lleva mucho tiempo. La depuración interactiva con GHCi parece ser una mejor herramienta para este trabajo, si tan solo supiera cómo usarlo.


Stack tiene algo de apoyo para esto. Running stack ghci --load-local-deps $TARGET cargará su proyecto y las dependencias que se encuentren en el campo de packages de stack.yaml , incluso si están marcados como stack.yaml extra-dep . Los puntos de interrupción funcionarán entonces. Puede depurar una dependencia en GHCi ejecutando stack unpack $PACKAGE y agregándolo a los packages en stack.yaml .

Esto no es una panacea sin embargo. Si los paquetes tienen extensiones de idioma de paquete global en conflicto (u otras marcas dinámicas) o conflictos de nombres de módulos, no funcionará. Por ejemplo, si su paquete de nivel superior tiene default-extensions: NoImplicitPrelude y sus dependencias no, no se importará un preludio y es casi seguro que no se cargará. Ver este error de GHC .