haskell - segun - monadologia leibniz resumen
Delimitando la mónada IO (2)
Es bueno saber (en Safe Haskell, al menos) de la firma si algo realiza o no acciones de IO, pero IO abarca muchas cosas diferentes: putStr
, acceso a la base de datos, eliminación y escritura de archivos, IORefs, etc.
Si estoy usando las firmas de tipo como una medida de seguridad cuando se ejecuta un código arbitrario, puede ser que esté dispuesto a aceptar algunas acciones de IO ( putStr
y el ilk, por ejemplo) pero no otras.
¿Hay una manera de definir una versión restringida de la mónada IO, con solo un subconjunto de las acciones IO normales? Si es así, un ejemplo (con putStr
, por ejemplo) sería muy bienvenido.
Como seguimiento a mi comentario, puede implementarlo usted mismo con algo como
class Monad io => Stdout io where
putStr_ :: String -> io ()
putStrLn_ :: String -> io ()
print_ :: Show a => a -> io ()
-- etc
instance Stdout IO where
putStr_ = putStr
putStrLn_ putStrLn
print_ = print
myFunc :: Stdout io => io ()
myFunc = do
val <- someAction
print_ val
let newVal = doSomething val
print_ newVal
main :: IO ()
main = myFunc
Esto no tendrá ninguna sobrecarga de tiempo de ejecución, ya que GHC optimizará esas clases de tipos para usar solo la mónada IO
, es extensible, fácil de escribir y se puede combinar con las transformaciones de mónada y la clase MonadIO
bastante facilidad. Si tiene varias clases, como una clase Stdin
con getLine_
, getChar_
, etc. definida, incluso puede combinar estas clases de tipos con
class (Stdout io, Stdin io) => StdOutIn io where
myFunc :: StdOutIn io => io ()
myFunc = do
val <- getLine_
putStrLn_ $ "Echo: " ++ val
main :: IO ()
main = myFunc
Simplemente defina un newtype
alrededor de IO a
con una instancia de Monad, defina las versiones envueltas de sus funciones preaprobadas y no exporte el constructor , de modo que solo las funciones que ajustó se puedan usar en la mónada.