很高兴知道(至少在Safe Haskell中)来自签名是否某些东西执行IO操作,但IO包含许多不同的东西 - putStr
,数据库访问,删除和写入文件, IORefs等
如果我在运行任意代码时使用类型签名作为安全措施,那么我可能会愿意接受一些IO操作 - 例如putStr
之类的 - 但不是其他。
有没有办法定义IO monad的受限版本,只有一部分正常的IO操作?如果是这样,一个例子(例如putStr
)将非常受欢迎!
答案 0 :(得分:24)
作为我评论的后续内容,您可以使用
之类的内容自行实现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
这绝对没有运行时开销,因为GHC会优化那些类型类只使用IO
monad,它是可扩展的,易于编写,并且可以与monad变换和MonadIO
结合使用上课很容易。如果您有多个类,例如定义了Stdin
,getLine_
等的getChar_
类,您甚至可以将这些类型类与
class (Stdout io, Stdin io) => StdOutIn io where
myFunc :: StdOutIn io => io ()
myFunc = do
val <- getLine_
putStrLn_ $ "Echo: " ++ val
main :: IO ()
main = myFunc
答案 1 :(得分:10)
只需使用Monad实例定义newtype
IO a
周围,定义预先批准的函数的包装版本,不导出构造函数,以便仅你包装的函数可以在monad中使用。