问题
I know as a fact, that we cant implement an IO monad independently, but I dont know why exactly. This code is an attempt to implement an imperative paradigm using functional language. Can you explain the difference between this example and true IO? It looks like function main implements the correct action order and remains lazy.
import System.IO.Unsafe
data Io a = Io a
runIO :: Io a -> a
runIO (Io a) = a
instance Monad Io where
return x = Io x
Io a >>= f = f a
-- internal side effect function
output :: Show a => a -> Io ()
output s = return $! unsafePerformIO $ print s
----------------------------------------------------------------
mainIO :: Io ()
mainIO = do output "A"
b <- return "B"
output b
output b
x <- return (undefined :: String)
return undefined
output "C"
head [output "C", output "C"]
output x
output "D"
test = runIO mainIO
output:
"A"
"B"
"B"
"C"
"C"
<interactive>: Prelude.undefined
回答1:
I'm not sure what you're trying to show. You've embedded an encoding of IO
in Haskell, using the existing implementation of IO
as a target.
The key is your use of unsafePerformIO
and print
--- primitives you're borrowing from the other IO system.
Consider: what if you didn't have any other IO system to lean on. So no print
or other way to call primitive IO functions. How would you implement IO?
So while you can implement the IO abstraction many ways in Haskell, you always have to fall on new runtime primitive functions to actually call into the operating system to do real IO. That's the bit that can't be implemented in Haskell natively.
As a reference , see the PhD thesis "A Functional Specification of Effects", Wouter Swierstra, which gives an overview of various ways IO and other effects have been encoded in Haskell, and defines a specification of IO as a purely functional data type (kind of an extension of what you've done).
来源:https://stackoverflow.com/questions/10447914/io-implementation-inside-haskell