Here is an example of how one could implement the IO monad in Java.
Up vote 4 down vote favorite 3 share g+ share fb share tw.
Or it is interpreter job, when it found actions in its way it call them. Or maybe something else? Is there good IO monad implementation in different language which can help to deeply understand what happening in main function.
Thank you. Edit: such 'hGetContents' confuses me a lot. And makes me unsure how IO really implemented.
Ok, let's say I have very simple pure haskell interpreter witch unfortunately has no IO support and for curiosity I want to add this IO actions to it(unsafeIO tricks also). It is hard to get it from GHC,hugs or others.. haskell io interpreter monads link|improve this question edited Jul 13 '11 at 22:50 asked Jul 11 '11 at 9:00KA1001447 71% accept rate.
– hvr Jul 11 '11 at 9:03 yes, many times. Could you pls refer me to which part would help me in my question. It more confusing when it says (...I should say that I'm not describing here exactly what a monad is (I don't even completely understand it myself) and my explanation shows only one possible way to implement the IO monad in Haskell.
For example, the hbc Haskell compiler implements IO monad via continuations...) – KA100 Jul 11 '11 at 12:25 3 Ignore hGetContents. It's implemented using unsafeInterleaveIO, which does trickery behind the scenes to allow lazy I/O. It's not a good example of how IO is supposed to work.
– C. A. McCann Jul 11 '11 at 13:37 1 If you want to know how IO is really implemented, start with the paper on the topic: research.microsoft.com/en-us/um/people/s... – Carl Jul 11 '11 at 20:06 thank you @Carl, interesting paper.
– KA100 Jul 11 '117 at 16:25.
Here is an example of how one could implement the IO monad in Java: package so. Io; import java.io" rel="nofollow">java.io" rel="nofollow">java.io" rel="nofollow">java.io. BufferedReader; import java.io" rel="nofollow">java.io" rel="nofollow">java.io" rel="nofollow">java.io.
IOException; import java.io" rel="nofollow">java.io" rel="nofollow">java.io" rel="nofollow">java.io. InputStreamReader; import static so.io" rel="nofollow">so.io.IOMonad. *; import static so.io" rel="nofollow">so.io.ConsoleIO.
*; /** * This is a type containing no data -- corresponds to () in Haskell. */ class Unit { public final static Unit VALUE = new Unit(); } /** * This type represents a function from A to R */ interface Function { public R apply(A argument); } /** * This type represents an action, yielding type R */ interface IO { /** * Warning! May have arbitrary side-effects!
*/ R unsafePerformIO(); } /** * This class, internally impure, provides pure interface for action sequencing (aka Monad) */ class IOMonad { static IO pure(final T value) { return new IO() { @Override public T unsafePerformIO() { return value; } }; } static IO join(final IO> action) { return new IO(){ @Override public T unsafePerformIO() { return action.unsafePerformIO().unsafePerformIO(); } }; } static IO fmap(final Function func, final IO action) { return new IO(){ @Override public B unsafePerformIO() { return func. Apply(action.unsafePerformIO()); } }; } static IO bind(IO action, Function> func) { return join(fmap(func, action)); } } /** * This class, internally impure, provides pure interface for interaction with stdin and stdout */ class ConsoleIO { static IO putStrLn(final String line) { return new IO() { @Override public Unit unsafePerformIO() { System.out. Println(line); return Unit.
VALUE; } }; }; // Java does not have first-class functions, thus this: final static Function> putStrLn = new Function>() { @Override public IO apply(String argument) { return putStrLn(argument); } }; final static BufferedReader in = new BufferedReader(new InputStreamReader(System. In)); static IO getLine = new IO() { @Override public String unsafePerformIO() { try { return in.readLine(); } catch (IOException e) { throw new RuntimeException(e); } } }; } /** * The program composed out of IO actions in a purely functional manner. */ class Main { /** * A variant of bind, which discards the bound value.
*/ static IO bind_(final IO a, final IO b) { return bind(a, new Function>(){ @Override public IO apply(Unit argument) { return b; } }); } /** * The greeting action -- asks the user for his name and then prints a greeting */ final static IO greet = bind_(putStrLn("Enter your name:"), bind(getLine, new Function>(){ @Override public IO apply(String argument) { return putStrLn(" " + argument + "! "); } })); /** * A simple echo action -- reads a line, prints it back */ final static IO echo = bind(getLine, putStrLn); /** * A function taking some action and producing the same action run repeatedly forever (modulo stack overflow :D) */ static IO loop(final IO action) { return bind(action, new Function>(){ @Override public IO apply(Unit argument) { return loop(action); } }); } /** * The action corresponding to the whole program */ final static IO main = bind_(greet, bind_(putStrLn("Entering the echo loop. "),loop(echo))); } /** * The runtime system, doing impure stuff to actually run our program.
*/ public class RTS { public static void main(String args) { Main.main.unsafePerformIO(); } } This is a runtime system implementing interface to the console I/O together with a small purely functional program which greets the user and then runs an echo loop. One can't implement the unsafe part in Haskell because Haskell is purely functional language. It is always implemented with lower-level facilities.
The IO monad is basically implemented as a state transformer (similar to State), with a special token RealWorld. Each IO operation depends on this token and passes it when it finishes. UnsafeInterleaveIO introduces a second token, so that a new IO operation can start, while the other one is still doing its work.
Usually, you don't have to care about the implementation. If you want to call IO-functions from other languages, GHC cares about removing the IO wrapper. Consider this small snippet: printInt :: Int -> IO () printInt int = do putStr "The argument is: " print int foreign export ccall printInt :: Int -> IO () This generates a symbol to call printInt from C.
The function becomes: extern void printInt(HsInt a1); Where HsInt is just a (depending on your platform) typedefd int. So you see, the monad IO has been removed completely.
If you want to understand the implementation of the IO monad, it's very well described in an award-winning paper by Phil Wadler and Simon Peyton Jones, who were the ones who figured out how to use monads to do input/output in a pure language. The paper is Imperative Functional Programming and is on both authors' web sites.
Thank you very much – KA100 Jul 14 '11 at 17:32.
I will leave the question of implementing IO to other people who know a bit more. (Though I will point out, as I'm sure they will as well, that the real question isn't "How is IO implemented in Haskell? " but rather "How is IO implemented in GHC?
" or "How is IO implemented in Hugs? ", etc. I imagine the implementations vary enormously. ) However, this question: how to call haskell function (IO) from another language and do I in that case need to maintain IO my self?
...is answered in depth in the FFI specification.
In fact "IO a" is just "() -> a" in an impure language (where functions can have side effect). Let's say you wan to implement IO in SML : structure Io : MONAD = struct type 'a t = unit -> 'a return x = fn () => x fun (ma >>= g) () = let a = ma () in g a () executeIo ma = ma () end.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.