3

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

1 Answer 1

11

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).

enter image description here

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for reply and the reference! Im new on this site, so if I ask some questions later in this topic will somebody notice it? Or will it be better to create a new topic?
By the way, my question appeared after reading this tutorial haskell.org/haskellwiki/IO_inside and this paper webcache.googleusercontent.com/…
An IO type defined as RealWorld->(a,RealWorld) is used here, so an action sequence is realized using the fake parameter RealWorld. But IMHO this model is impossible in pure language without outer compiler hacks. So I wonder why this implementation is used, hope that pdf has more clearly explanation.
@user1374768: It's best to ask a new question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.