haskell - preestablecida - monadas leibniz
¿Haskell-doble personalidad IO/ST mónada? (2)
Tengo un código que actualmente usa una mónada ST para la evaluación. No me gusta poner IO en todas partes porque el método runST
produce un resultado puro e indica que es seguro llamar a ese resultado (en lugar de unsafePerformIO
). Sin embargo, como parte de mi código se ha vuelto más largo, quiero poner las declaraciones de impresión de depuración en.
¿Hay alguna clase que ofrezca una mónada de doble personalidad [o maquinaria de clase de tipos], una que pueda ser una ST o una IO (según su tipo o una bandera "isDebug")? Recuerdo que SPJ introdujo una clase de "Mutación" en su artículo "Diversión con funciones tipográficas", que usaba tipos asociativos para relacionar IO con IORef y ST con STRef. ¿Existe tal como un paquete en alguna parte?
Edición / solución
Muchas gracias [la novena vez], CA McCann! Usando esa solución, pude introducir una clase adicional para las mónadas que admiten una función pdebug
. La mónada ST
ignorará estas llamadas, mientras que IO
ejecutará putStrLn
.
class DebugMonad m where
pdebug :: String -> m ()
instance DebugMonad (ST s) where
pdebug _ = return ()
instance DebugMonad IO where
pdebug = putStrLn
test initV = do
v <- newRef initV
modifyRef v (+1)
pdebug "debug"
readRef v
testR v = runST $ test v
Esto tiene una consecuencia muy afortunada en ghci. Como espera que las expresiones sean de tipo IO de forma predeterminada, ejecutar algo como "prueba 3" dará como resultado que se ejecute la mónada IO, por lo que puede depurarlo fácilmente y luego llamarlo con algo como "testR" cuando realmente desee ejecutar eso.
¿Has considerado Debug.Trace.trace en su lugar?
Si desea una interfaz unificada para IORef
y STRef
, ¿ha mirado el paquete stateref
? Tiene clases de tipo para "referencias a datos mutables", separadas para legibles, grabables, etc., con instancias para IORef
y STRef
, así como cosas como TVar
, MVar
, ForeignPtr
, etc.