Why don't these functions return the same result? [duplicate] - haskell

As far as I know, do blocks in Haskell are just some kind of syntactic sugar for monadic bind operators. For example, one could convert
main = do f <- readFile "foo.txt"
print f
print "Finished"
to
main = readFile "foo.txt" >>= print >> print "Finished"
Can all do blocks be converted to bind syntax? What about, for example, this block where f is used multiple times:
main = do f <- readFile "foo.txt"
print $ "prefix " ++ f
print $ f ++ " postfix"
Assuming we are in the IO monad, it is not possible to simply execute the readFile computation twice. How can this example (if possible at all) expressed using only bind syntax?
I think using Control.Monad is no solution, because it internally uses do blocks.
I think it it's possible to express this using arrows (using &&&) -- maybe this is a case where only arrows can be used as a generalization of monads?
Note that this question is not about the special examples above but about the general case of the result of a computation being used multiple times in monadic expressions like print.

Yes, all of them can be converted to bind syntax; in fact, they are converted internally by the compiler.
I hope this translation of your example gives you the hint:
main = readFile "foo.txt" >>= \f ->
(print $ "prefix " ++ f) >>
(print $ f ++ " postfix")

The Report gives a full translation from do syntax into kernel Haskell:
Do expressions satisfy these identities, which may be used as a translation into the kernel, after eliminating empty stmts:
do {e} = e
do {e;stmts} = e >> do {stmts}
do {p <- e; stmts} = let ok p = do {stmts}
ok _ = fail "..."
in e >>= ok
do {let decls; stmts} = let decls in do {stmts}
The ellipsis "..." stands for a compiler-generated error message, passed to fail, preferably giving some indication of the location of the pattern-match failure; the functions >>, >>=, and fail are operations in the class Monad, as defined in the Prelude; and ok is a fresh identifier.
So your example translates this way:
do f <- readFile "foo.txt"
print $ "prefix " ++ f
print $ f ++ " postfix"
=
let ok f = do print $ "prefix " ++ f
print $ f ++ " postfix"
ok _ = fail "..."
in readFile "foo.txt" >>= ok
=
let ok f = (print $ "prefix " ++ f) >> do print $ f ++ " postfix"
ok _ = fail "..."
in readFile "foo.txt" >>= ok
=
let ok f = (print $ "prefix " ++ f) >> (print $ f ++ " postfix")
ok _ = fail "..."
in readFile "foo.txt" >>= ok
This version has no do blocks, but doesn't look very natural. But we can apply equational reasoning and whatever optimizations we know. So, for example, observing that the ok _ = fail "..." clause is dead code, we could inlike ok like so:
=
readFile "foo.txt" >>= \f ->
(print $ "prefix " ++ f) >>
(print $ f ++ " postfix")
All do blocks can be mechanically translated into code without do in this way.

Related

Using (_ <- f) instead of f Alone?

Looking at this ZeroMQ HelloWorldClient.hs code snippet:
forM_ [1..10] $ \i -> do
liftIO . putStrLn $ "Sending Hello " ++ show i ++ "…"
send requester [] "Hello"
_ <- receive requester
liftIO . putStrLn $ "Received World " ++ show i
Is there any reason why _ <- receive requester wouldn't be written as receive requester?
Also, in general, is there any reason to use _ <- f (where f : Monad m => m a) instead of f?
That's a common way to silence warnings about throwing away a value, when you've got something of type m a where a is not (). Another common way to do this is with void.

Can I be sure of order of IO actions in this example?

At the moment, I have this code in and around main:
import Control.Monad
import Control.Applicative
binSearch :: Ord a => [a] -> a -> Maybe Int
main = do
xs <- lines <$> readFile "Cars1.txt"
x <- getLine <* putStr "Registration: " -- Right?
putStrLn $ case binSearch xs x of
Just n -> "Found at position " ++ show n
Nothing -> "Not found"
My hope is for “Registration: ” to be printed, then for the program to wait for the input to x. Does what I've written imply that that will be the case? Do I need the <*, or will putting the putStr expression on the line above make things work as well?
PS: I know I have to convert binSearch to work with arrays rather than lists (otherwise it's probably not worth doing a binary search), but that's a problem for another day.
The line
x <- getLine <* putStr "Registration: "
orders the IO actions left-to-right: first a line is taken as input, then the message is printed, and finally variable x is bound to the result of getLine.
Do I need the <*, or will putting the putStr expression on the line
above make things work as well?
If you want the message to precede the input, you have to put the putStr on the line above, as follows:
main :: IO ()
main = do
xs <- lines <$> readFile "Cars1.txt"
putStr "Registration: "
x <- getLine
putStrLn $ case binSearch xs x of
Just n -> "Found at position " ++ show n
Nothing -> "Not found"
Alternatively,
x <- putStr "Registration: " *> getLine
or
x <- putStr "Registration: " >> getLine
would work, but they are less readable.
Finally, since you added the lazy-evaluation tag, let me add that your question is actually not about laziness, but about how the operator <* is defined, and in particular about the order in which it sequences the IO actions.

Expressing do block using only monadic bind syntax

As far as I know, do blocks in Haskell are just some kind of syntactic sugar for monadic bind operators. For example, one could convert
main = do f <- readFile "foo.txt"
print f
print "Finished"
to
main = readFile "foo.txt" >>= print >> print "Finished"
Can all do blocks be converted to bind syntax? What about, for example, this block where f is used multiple times:
main = do f <- readFile "foo.txt"
print $ "prefix " ++ f
print $ f ++ " postfix"
Assuming we are in the IO monad, it is not possible to simply execute the readFile computation twice. How can this example (if possible at all) expressed using only bind syntax?
I think using Control.Monad is no solution, because it internally uses do blocks.
I think it it's possible to express this using arrows (using &&&) -- maybe this is a case where only arrows can be used as a generalization of monads?
Note that this question is not about the special examples above but about the general case of the result of a computation being used multiple times in monadic expressions like print.
Yes, all of them can be converted to bind syntax; in fact, they are converted internally by the compiler.
I hope this translation of your example gives you the hint:
main = readFile "foo.txt" >>= \f ->
(print $ "prefix " ++ f) >>
(print $ f ++ " postfix")
The Report gives a full translation from do syntax into kernel Haskell:
Do expressions satisfy these identities, which may be used as a translation into the kernel, after eliminating empty stmts:
do {e} = e
do {e;stmts} = e >> do {stmts}
do {p <- e; stmts} = let ok p = do {stmts}
ok _ = fail "..."
in e >>= ok
do {let decls; stmts} = let decls in do {stmts}
The ellipsis "..." stands for a compiler-generated error message, passed to fail, preferably giving some indication of the location of the pattern-match failure; the functions >>, >>=, and fail are operations in the class Monad, as defined in the Prelude; and ok is a fresh identifier.
So your example translates this way:
do f <- readFile "foo.txt"
print $ "prefix " ++ f
print $ f ++ " postfix"
=
let ok f = do print $ "prefix " ++ f
print $ f ++ " postfix"
ok _ = fail "..."
in readFile "foo.txt" >>= ok
=
let ok f = (print $ "prefix " ++ f) >> do print $ f ++ " postfix"
ok _ = fail "..."
in readFile "foo.txt" >>= ok
=
let ok f = (print $ "prefix " ++ f) >> (print $ f ++ " postfix")
ok _ = fail "..."
in readFile "foo.txt" >>= ok
This version has no do blocks, but doesn't look very natural. But we can apply equational reasoning and whatever optimizations we know. So, for example, observing that the ok _ = fail "..." clause is dead code, we could inlike ok like so:
=
readFile "foo.txt" >>= \f ->
(print $ "prefix " ++ f) >>
(print $ f ++ " postfix")
All do blocks can be mechanically translated into code without do in this way.

Performing an operation without doing the evaluation

Suppose we have a function like this:
f:Int->Int
which gives us a modified output based on the input.
My question is, is there anyway I can write this function,so that no evaluation is done on the input? For instance consider the following expected input and output:
Input: 3+2/1+90
Output: 3+2/1+90+2
[Edit]
I had heard about Haskell's lazy evaluation, but I just realized that it's exactly what I wanted and as long as I don't call the print, actually no evaluation is done in the parse tree.
In Haskell things are always lazy, so you're always going to have a computation equivalent to 3+2/1+90+2 but when you ask for the printed version, you'll evaluate it.
You can do stuff like this
f x = x + 2
main = do
let x = f (error "Kaboom!!")
print 1
And run it just fine, but trying to print it will force evaluation.
main = do
let x = f (error "Kaboom!!")
print x
Which will error. The story has some subtleties with how much/when things are evaluated, but that's the gist of it.
At this point, Haskell has lost all ability to "pretty print" a computation, all of the information has been compiled away into explicit closures and other ugliness. If you want to watch to computation build up, there is a kinda fun trick
newtype TraceableNum = Trace { runTrace :: String }
instance Num TraceableNum where
(Trace a) + (Trace b) = Trace $ "(" ++ a ++ " + " ++ b ++ ")"
(Trace a) - (Trace b) = Trace $ "(" ++ a ++ " - " ++ b ++ ")"
(Trace a) * (Trace b) = Trace $ "(" ++ a ++ " * " ++ b ++ ")"
abs (Trace a) = Trace $ "abs(" ++ a ++ ")"
signum (Trace a) = Trace $ "signum(" ++ a ++ ")"
fromInteger = Trace . show
main = print . runTrace $ 1 + 4 * 7
Daniel Wagner pointed out if you want to continue with this idea: simple-reflect

Haskell, can i call function without IO output working with monads?

Why i can't do this?
Its forbidden the use of 'do' in this question :/
How i can call words in my list and at same time result an IO?
Thanks.. this is my actual code :/
main :: IO()
main =
putStr "Name of File: " >>
getLine >>=
\st ->
openFile st ReadMode >>=
\handle ->
hGetContents handle >>=
\y ->
words y >>=
\strings ->
strings !! 1 >>=
\string->
putStr string
[Edit] Solution :
main :: IO()
main =
putStr "Name of File: " >>
getLine >>=
\st ->
openFile st ReadMode >>=
\handle ->
hGetContents handle >>=
\y ->
return (words y) >>=
\strings ->
return (strings !! 1) >>=
\string->
putStr string
Use return (words y) instead of just words y. return wraps a pure value (such as the [String] that words returns) into a monad.
From your wording, it sounds like this question is homework. If so, it should be tagged as such.
(This doesn't directly answer the question, but it will make your code more idiomatic and thus easier to read.)
You are using the pattern \x -> f x >>= ... a lot, this can (and should) be eliminated: it is (mostly) unnecessary noise which obscures the meaning of the code. I won't use your code, since it is homework but consider this example (note that I'm using return as suggested by the other answer):
main = getLine >>=
\fname -> openFile fname ReadMode >>=
\handle -> hGetContents handle >>=
\str -> return (lines str) >>=
\lns -> return (length lns) >>=
\num -> print num
(It reads a file name from the user, and then prints the number of lines in that file.)
The easiest optimisation is the section where we count the number of lines (this corresponds to the part where you are separating the words and getting the second one): the number of lines in a string str is just length (lines str) (which is the same as length . lines $ str), so there is no reason for us to have the call to length and the call to lines separate. Our code is now:
main = getLine >>=
\fname -> openFile fname ReadMode >>=
\handle -> hGetContents handle >>=
\str -> return (length . lines $ str) >>=
\num -> print num
Now, the next optimisation is on \num -> print num. This can be written as just print. (This is called eta conversion). (You can think about this as "a function that takes an argument and calls print on it, is the same as print itself"). Now we have:
main = getLine >>=
\fname -> openFile fname ReadMode >>=
\handle -> hGetContents handle >>=
\str -> return (length . lines $ str) >>= print
The next optimisation we can do is based on the monad laws. Using the first one, we can turn return (length . lines $ str) >>= print into print (length . lines $ str) (i.e. "creating a container that contains a value (this is done by return) and then passing that value to print is the same as just passing the value to print"). Again, we can remove the parenthesis, so we have:
main = getLine >>=
\fname -> openFile fname ReadMode >>=
\handle -> hGetContents handle >>=
\str -> print . length . lines $ str
And look! We have an eta-conversion we can do: \str -> print . length . lines $ str becomes just print . length . lines. This leaves:
main = getLine >>=
\fname -> openFile fname ReadMode >>=
\handle -> hGetContents handle >>= print . length . lines
At this point, we can probably stop, since that expression is much simpler than our original one (we could keep going, by using >=> if we wanted to). Since it is so much simpler, it is also easier to debug (imagine if we had forgotten to use lines: in the original main it wouldn't be very clear, in the last one it's obvious.)
In your code, you can and should do the same: you can use things like sections (which mean \x -> x !! 1 is the same as (!! 1)), and the eta conversion and monad laws I used above.

Resources