Ответ 1
В качестве продолжения моего комментария вы можете реализовать его сами с чем-то вроде
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
, она расширяема, проста в написании и может быть легко скомбинирована с преобразованиями монады и классом 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