
Hi, Can someone please explain how IO operations do not fit in the pure category of mathematical function in that they have to be implemented via Monads. For e.g. the getLine function has the type IOString and it reads the input from the user. Now as I see it the output of getLine will always be same if the input remain same (i.e. for input "X" getLine will always return "X" ) which is the constraint on mathematical functions. Therefore I don't see why monads are necessary for implementing IO in pure languages. I can understand why Date and Random functions have be implemented via monads because their output will always change. Thanks, Shishir

Hi Shishir, I explain it to myself as the nondeterministic behavior of the user which would lead to the impurity.
From the perspective of the programm, you just call a function without argument that returns a string. And every call has the potential to return something totally different depending on the users behavior.
So what you called input is not the input in the sense of an functional argument which is the foundation of the definition of purity. I am myself an absolute beginner in Haskell and Functional Thinking so I hope to get some constructive feedback on my mental image of this situation. Cheers Jakob On 04/26/2015 11:59 AM, Shishir Srivastava wrote:
Hi,
Can someone please explain how IO operations do not fit in the pure category of mathematical function in that they have to be implemented via Monads.
For e.g. the getLine function has the type IOString and it reads the input from the user. Now as I see it the output of getLine will always be same if the input remain same (i.e. for input "X" getLine will always return "X" ) which is the constraint on mathematical functions.
Therefore I don't see why monads are necessary for implementing IO in pure languages.
I can understand why Date and Random functions have be implemented via monads because their output will always change.
Thanks, Shishir
_______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
-- Jakob Holderbaum, M.Sc. Embedded Software Engineer 0176 637 297 71 http://jakob.io/ http://jakob.io/mentoring/ hi@jakob.io @hldrbm

The IO Monad provides a way to construct imperative programs in a pure
manner. For example,
print x = putStrLn (show x)
The function 'print' can be thought of as returning the same 'IO
computation' for same values of x.
Using the Monad interface, these instructions can be combined, like
main = getLine >>= print
which is equivalent to
main = do
x <- getLine
print x
Just like this, many IO values can be stitched together to create larger IO
values, which are descriptions of imperative programs as above.
It is pure, as the same 'computation' is returned for the same arguments.
On 26 April 2015 at 15:46, Jakob Holderbaum
Hi Shishir,
I explain it to myself as the nondeterministic behavior of the user which would lead to the impurity.
From the perspective of the programm, you just call a function without argument that returns a string. And every call has the potential to return something totally different depending on the users behavior.
So what you called input is not the input in the sense of an functional argument which is the foundation of the definition of purity.
I am myself an absolute beginner in Haskell and Functional Thinking so I hope to get some constructive feedback on my mental image of this situation.
Cheers Jakob
Hi,
Can someone please explain how IO operations do not fit in the pure category of mathematical function in that they have to be implemented via Monads.
For e.g. the getLine function has the type IOString and it reads the input from the user. Now as I see it the output of getLine will always be same if the input remain same (i.e. for input "X" getLine will always return "X" ) which is the constraint on mathematical functions.
Therefore I don't see why monads are necessary for implementing IO in
On 04/26/2015 11:59 AM, Shishir Srivastava wrote: pure
languages.
I can understand why Date and Random functions have be implemented via monads because their output will always change.
Thanks, Shishir
_______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
-- Jakob Holderbaum, M.Sc. Embedded Software Engineer
0176 637 297 71 http://jakob.io/ http://jakob.io/mentoring/ hi@jakob.io @hldrbm
_______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
-- Regards Sumit Sahrawat

On Sun, Apr 26, 2015 at 5:16 PM, Jakob Holderbaum
I am myself an absolute beginner in Haskell and Functional Thinking so I hope to get some constructive feedback on my mental image of this situation.
When you write: "From the perspective of the programm, you just call a function without argument that returns a string" you veer close to the lousy thinking that Everything is a Function. Conal Elliott did the delousing here: http://conal.net/blog/posts/everything-is-a-function-in-haskell Have a read, and if you're not convinced, come back here and ask for more help. -- Kim-Ee

Thanks for removing a misconception about everything being a function.
My original example used writeFile, which is why I used the term 'function'.
Refactoring text is more difficult as compared to haskell code :)
On 26 April 2015 at 17:34, Kim-Ee Yeoh
On Sun, Apr 26, 2015 at 5:16 PM, Jakob Holderbaum
wrote: I am myself an absolute beginner in Haskell and Functional Thinking so I hope to get some constructive feedback on my mental image of this situation.
When you write: "From the perspective of the programm, you just call a function without argument that returns a string"
you veer close to the lousy thinking that Everything is a Function. Conal Elliott did the delousing here:
http://conal.net/blog/posts/everything-is-a-function-in-haskell
Have a read, and if you're not convinced, come back here and ask for more help.
-- Kim-Ee
_______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
-- Regards Sumit Sahrawat

On Sun, Apr 26, 2015 at 4:59 PM, Shishir Srivastava < shishir.srivastava@gmail.com> wrote:
For e.g. the getLine function has the type IOString and it reads the input from the user. Now as I see it the output of getLine will always be same if the input remain same (i.e. for input "X" getLine will always return "X" ) which is the constraint on mathematical functions.
Notice that getLine is not a function. It is a value of type IO String. In the misty dawn of Haskell, how you'd achieve the same thing as getLine is to actually use Dialogue functions. And yes, a value of type Dialogue is a bona fide function because Dialogue is a type synonym for [Response] -> [Request]. You can read a bit about Haskell 1.2 and IO here: http://r6.ca/blog/20110520T220201Z.html Now Haskell 1.2 dates from 1992. Certainly it would be an experience playing with it. Unfortunately, I know of no way to get hold of a compiler or interpreter that old. You might want to query haskell-cafe. Returning to getLine and monadic I/O, a question to contemplate is: how is getLine different from an ordinary String, say "hello world"? -- Kim-Ee

Shishir, I'll reply as an humble programmer, not a category theorist. For me the clarifying example was to contrast putStrLn (getLine ++ getLine) with s = square 3 + square 4 where square x = x * x There is absolutely nothing that "leaks" between the two sub-expressions involving square, so I'm free to rewrite as: a = square 3 b = square 4 s = a + b or b = square 4 a = square 3 s = a + b or x = square 7 b = square 4 a = square 3 s = a + b y = square 8 or hh m n = square m + square n x = square 7 s = hh 3 4 y = square 8 without altering the value of s or any surrounding computation. In that last case, I can now freely intermingle uses of hh and square without risk. But if I were to attempt the same gymnastics with putStrLn and getLine, I wouldn't have those freedoms. The order of evaluation/performance now becomes critical. So the monad provides a way to manage the composition, and the type system ensures visibility to the fact that something more is going on when a defined function includes IO behavior. Hope that helps, -jn- On Sun, Apr 26, 2015 at 4:59 AM, Shishir Srivastava < shishir.srivastava@gmail.com> wrote:
Hi,
Can someone please explain how IO operations do not fit in the pure category of mathematical function in that they have to be implemented via Monads.
For e.g. the getLine function has the type IOString and it reads the input from the user. Now as I see it the output of getLine will always be same if the input remain same (i.e. for input "X" getLine will always return "X" ) which is the constraint on mathematical functions.
Therefore I don't see why monads are necessary for implementing IO in pure languages.
I can understand why Date and Random functions have be implemented via monads because their output will always change.
Thanks, Shishir
_______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
-- Beauty of style and harmony and grace and good rhythm depend on simplicity. - Plato

You can't do
putStrLn (getLine ++ getLine)
so of course you can't do such transformations. I would suggest you rewrite
your IO action without any syntactic sugar (with plain >> and >>=) first
and then try to do transformations.
I general, I find it useful to think of IO actions in two ways:
- as a value of IO type that your main is (kind of instructions that
Haskell runtime should perform).
- the effects execution of this value causes.
You can think that the sole purpose of your program is to construct this IO
value, while its execution is performed kind of outside of your program. If
you think that way, IO is again pure, obeys all monad rules and
categorically valid monad.
Regards,
Alexey Shmalko
On Sun, Apr 26, 2015 at 3:22 PM Joel Neely
Shishir,
I'll reply as an humble programmer, not a category theorist. For me the clarifying example was to contrast
putStrLn (getLine ++ getLine)
with
s = square 3 + square 4
where
square x = x * x
There is absolutely nothing that "leaks" between the two sub-expressions involving square, so I'm free to rewrite as:
a = square 3 b = square 4 s = a + b
or
b = square 4 a = square 3 s = a + b
or
x = square 7 b = square 4 a = square 3 s = a + b y = square 8
or
hh m n = square m + square n x = square 7 s = hh 3 4 y = square 8
without altering the value of s or any surrounding computation. In that last case, I can now freely intermingle uses of hh and square without risk.
But if I were to attempt the same gymnastics with putStrLn and getLine, I wouldn't have those freedoms. The order of evaluation/performance now becomes critical.
So the monad provides a way to manage the composition, and the type system ensures visibility to the fact that something more is going on when a defined function includes IO behavior.
Hope that helps, -jn-
On Sun, Apr 26, 2015 at 4:59 AM, Shishir Srivastava < shishir.srivastava@gmail.com> wrote:
Hi,
Can someone please explain how IO operations do not fit in the pure category of mathematical function in that they have to be implemented via Monads.
For e.g. the getLine function has the type IOString and it reads the input from the user. Now as I see it the output of getLine will always be same if the input remain same (i.e. for input "X" getLine will always return "X" ) which is the constraint on mathematical functions.
Therefore I don't see why monads are necessary for implementing IO in pure languages.
I can understand why Date and Random functions have be implemented via monads because their output will always change.
Thanks, Shishir
_______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
-- Beauty of style and harmony and grace and good rhythm depend on simplicity. - Plato _______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

Can someone please explain how IO operations do not fit in the pure category of mathematical function in that they have to be implemented via Monads.
Let's not talk about monads at all. Instead allow me to eliminate a major misconception right away: I/O does in fact fit into the model of purity. The first major insight occurs when you stop thinking about getLine as a function or an "impure value". What it really is is just a program. Every value of type `IO A` is in fact a program that produces a value of type `A`. The second major insight happens when you realise that the equal sign in Haskell introduces an actual equation: line = getLine Here `line` is not a string either. You have just expressed that `line` is the exact same thing as `getLine`, so it is a program that, when run, produces a string. Now realise that `main` is also a program, the one that is the actual program you are writing. When putStrLn "Hello!" is a program that prints a string and results in the dummy value `()` and you say that main = putStrLn "Hello!" then the program you are writing is that same program, because you have just defined it to be (remember: equation, not assignment!). Now you have a bunch of programs. The final ingredient to writing side-effecting programs in Haskell is a way to combine those programs. If `p1` and `p2` are two programs, then `p1 >> p2` is the program that first executes `p1` and then executes `p2`. Its result is the result of `p2`, the latter argument of `(>>)`: main = putStrLn "Hello" >> putStrLn "world!" You have just defined `main` (i.e. your program) to be the program that first prints the "Hello" line, then prints the "world!" line. A more powerful operator is `(>>=)`, which is best explained in terms of an example: putStrLn :: String -> IO () Now this is an actual function. It takes a string and returns a program, the one that prints that string. Remember that functions are the things that can be applied. Not everything is a function, and in particular programs are *not* functions, a common and dangerous misconception. You could just pass it a string, but what if you want to print whatever `getLine` resulted in? (>>=) :: IO a -> (a -> IO b) -> IO b Verify that the first argument fits the type of `getLine`, the second one fits the type of `putStrLn`. Here is the specialised version, where `a = String` and `b = ()`: (>>=) :: IO String -> (String -> IO ()) -> IO () Simply apply it to the desired program (`getLine`) and the desired program-producing function (`putStrLn`) to get a composite program: main = getLine >>= putStrLn Now let's talk about monads. It is a nice incident that the `(>>=)` operator follows a nice algebraic structure (monads), just like addition follows a nice algebraic structure (monoids). And it is not the only operator that follows this structure. What we can do now is to write extremely generic functions that work for all monads with a single implementation. Welcome to the world of composable polymorphism. This is the main reason why Haskell code tends to be much shorter than code in other languages. Functions like `mapM` and `forever` are not IO-specific. They work for all monads, yet they have only a single implementation. So yes, you are right. Monads are not at all necessary. But they are useful, because we get so much for free. Basically when you implement a control functions, chances are that you can actually apply it to a wide variety of structures, including `IO`. Exercise: Can you think of an operation that would work for all monoids? If you can, you can implement it *in its general form* in Haskell. In other words, once you have established that some type denotes a monoid, that operation will be available for it for free. Same thing with monads.
For e.g. the getLine function has the type IOString and it reads the input from the user. Now as I see it the output of getLine will always be same if the input remain same (i.e. for input "X" getLine will always return "X" ) which is the constraint on mathematical functions.
Therefore I don't see why monads are necessary for implementing IO in pure languages.
I can understand why Date and Random functions have be implemented via monads because their output will always change.
participants (7)
-
Alexey Shmalko
-
Ertugrul Söylemez
-
Jakob Holderbaum
-
Joel Neely
-
Kim-Ee Yeoh
-
Shishir Srivastava
-
Sumit Sahrawat, Maths & Computing, IIT (BHU)