Why can't I force an IO action with seq? - haskell

Given this code snippet:
someFunction x = print x `seq` 1
main = do print (someFunction "test")
why doesn't the print x print test when the code is executed?
$./seq_test
1
If I replace it with error I can check that the left operand of seq is indeed evaluated.
How could I achieve my expected output:
test
1
modifying only someFunction?

Evaluating an IO action does nothing whatsoever. That's right!
If you like, values of IO type are merely "instruction lists". So all you do with that seq is force the program to be sure1 of what should be done if the action was actually used. And using an action has nothing to do with evaluation, it means monadically binding it to the main call. But since, as you say, someFunction is a function with a non-monadic signature, that can't happen here.
What you can do... but don't, is
import Foreign
someFunction x = unsafePerformIO (print x) `seq` 1
this actually couples evaluation to IO execution. Which normally is a really bad idea in Haskell, since evaluation can happen at completely unforseeable order, possibly a different number of times than you think (because the compiler assumes referential transparency), and other mayhem scenarios.
The correct solution is to change the signature to be monadic:
someFunction :: Int -> IO Int
someFunction x = do
print x
return 1
main = do
y <- someFunction "test"
print y
1And as it happens, the program is as sure as possible anyway, even without seq. Any more details can only be obtained by executing the action.

seq evaluated expressions to weak head normal form, which is simply the outermost constructor (or lambda application). The expression print x is already in WHNF, so seq doesn't do anything.
You can get the result you're looking for with the function Debug.Trace.trace.

Related

Haskell. How to do IO inside pure Haskell function? How to print intermediate results while function is being executed? [duplicate]

This question already has answers here:
How to get normal value from IO action in Haskell
(2 answers)
Closed 1 year ago.
In many imperative programming languages like Java, C or Python we can easily add a print function which can give us information about the intermediate state of the program.
My goal is to find a way to do something like that in Haskell. I want the function which not only computes value but also prints something. The function below is a simplified version of what I want to do. My actual function is too complicated and incomprehensive without context to show it here.
My idea is to have a "pure" Haskell function that has an auxiliary function inside which has [Int] -> IO () -> Int type signature. An IO parameter is initialized in the where clause as a do block. But unfortunately, the do block is not executed, when I run the function in GHCI. The function is compiled successfuly though
module Tests where
-- Function returns the sum of the list and tries to print some info
-- but no IO actually happens
pureFuncWithIO :: [Int] -> Int
pureFuncWithIO [] = 0
pureFuncWithIO nums = auxIOfunc nums (return ())
where
auxIOfunc [] _ = 0
auxIOfunc (n : ns) _ = n + auxIOfunc ns (sneakyIOaction n)
sneakyIOaction n
= do -- Not executed
putStrLn $ "adding " ++ (show n);
return ()
Output in GHCI test:
*Tests> pureFuncWithIO [1,2,3,4,5]
15
Meanwhile, I expected something like this:
*Tests> pureFuncWithIO [1,2,3,4,5]
adding 1
adding 2
adding 3
adding 4
adding 5
15
Is it possible to come up with a way to have IO inside, keeping the return type of the outer-most function, not an IO a flavor? Thanks!
This type signature
pureFuncWithIO :: [Int] -> Int
is promising to the caller that no side effect (like prints) will be observed. The compiler will reject any attempt to perform IO. Some exceptions exist for debugging (Debug.Trace), but they are not meant to be left in production code. There also are some "forbidden", unsafe low-level functions which should never be used in regular code -- you should pretend these do not exist at all.
If you want to do IO, you need an IO return type.
pureFuncWithIO :: [Int] -> IO Int
Doing so allows to weave side effects with the rest of the code.
pureFuncWithIO [] = return 0
pureFuncWithIO (n : ns) = do
putStrLn $ "adding " ++ show n
res <- pureFuncWithIO ns
return (n + res)
A major point in the design of Haskell is to have a strict separation of functions which can not do IO and those who can. Doing IO in a non-IO context is what the Haskell type system was designed to prevent.
Your sneakyIOaction is not executed because you pass its result as a parameter to auxIOfunc, but never use that parameter, and haskell being lazy bastard it is never execute it.
If you try to use said parameter you find out that you can't. It's type not allow you to do anithing with it except combine with other IO things.
There is a way to do what you want, but it is on dark side. You need unsafePerformIO
unsafePerformIO :: IO a -> a
That stuff basically allow you to execute any IO. Tricky thing you have to consume result, otherwise you may end up with haskell skip it due to its laziness. You may want to look into seq if you really want to use it, but don't actually need result.

Why is getLine being evaluated when its value is not required?

If Haskell is lazy, why does getLine is evaluated in both of the following cases? Being lazy I would expect that in the case of fa the getLine would not be evaluated because its result is not being used subsequently:
let fa = do {
x <- getLine;
return "hello"
}
let fb = do {
x <- getLine;
return $ x
}
(I tested both cases in GHCi)
Thanks
Its result is being used, just not in the way you necessarily expect. This de-sugars to
fa = getLine >>= (\x -> return "hello")
So the result of getLine is still passed to the function \x -> return "hello". Monads are inherently about sequencing actions together (among other things); that sequencing still occurs even if results are later not used. If that weren't the case, then
main = do
print "Hello"
print "World"
wouldn't do anything as a program, since the results of both calls to print aren't being used.
Congratulations, you've just discovered why Haskell is a pure functional language!
The result† of getLine is not a string. It's an IO action which happens to “produce” a string. That string is indeed not evaluated, but the action itself is (since it turns up in a do block bound to main), and this is all that matters as far as side-effects are concerned.
†Really just the value of getLine. This is not a function, so it doesn't actually have a result.
Be careful now... ;-)
The result of getLine isn't a string, it's an "I/O command object", if you will. The code actually desugars to
getLine >>= (\ x -> return "hello")
The >>= operator constructs a new I/O command object out of an existing one and a function... OK, that's a bit much to wrap your mind around. The important thing is, the I/O action gets executed (because of the implementation of >>= for IO), but its result doesn't necessarily get evaluated (because of laziness).
So let's look at the implementation of the IO monad... erm, actually you know what? Let's not. (It's deep magic, hard-wired into the compiler, and as such it's implementation-specific.) But this phenomenon isn't unique to IO by any means. Let's look at the Maybe monad:
instance Monad Maybe where
mx >>= f =
case mx of
Nothing -> Nothing
Just x -> f x
return x = Just x
So if I do something like
do
x <- foobar
return "hello"
Will x get evaluated? Let's look. It desugars to:
foobar >>= (\ x -> return "hello")
then this becomes
case foobar of
Nothing -> Nothing
Just x -> Just "hello"
As you can see, foobar is clearly going to be evaluated, because we need to know whether the result is Nothing or Just. But the actual x won't be evaluated, because nothing looks at it.
It's kind of the same way that length evaluates the list nodes, but not the list elements they point to.

Haskell Input to create a String List

I would like to allow a user to build a list from a series of inputs in Haskell.
The getLine function would be called recursively until the stopping case ("Y") is input, at which point the list is returned.
I know the function needs to be in a similar format to below. I am having trouble assigning the correct type signatures - I think I need to include the IO type somewhere.
getList :: [String] -> [String]
getList list = do line <- getLine
if line == "Y"
then return list
else getList (line : list)
So there's a bunch of things that you need to understand. One of them is the IO x type. A value of this type is a computer program that, when later run, will do something and produce a value of type x. So getLine doesn't do anything by itself; it just is a certain sort of program. Same with let p = putStrLn "hello!". I can sequence p into my program multiple times and it will print hello! multiple times, because the IO () is a program, as a value which Haskell happens to be able to talk about and manipulate. If this were TypeScript I would say type IO<x> = { run: () => Promise<x> } and emphatically that type says that the side-effecting action has not been run yet.
So how do we manipulate these values when the value is a program, for example one that fetches the current system time?
The most fundamental way to chain such programs together is to take a program that produces an x (an IO x) and then a Haskell function which takes an x and constructs a program which produces a y (an x -> IO y and combines them together into a resulting program producing a y (an IO y.) This function is called >>= and pronounced "bind". In fact this way is universal, if we add a program which takes any Haskell value of type x and produces a program which does nothing and produces that value (return :: x -> IO x). This allows you to use, for example, the Prelude function fmap f = (>>= return . f) which takes an a -> b and applies it to an IO a to produce an IO b.
So It is so common to say things like getLine >>= \line -> putStrLn (upcase line ++ "!") that we invented do-notation, writing this as
do
line <- getLine
putStrLn (upcase line ++ "!")
Notice that it's the same basic deal; the last line needs to be an IO y for some y.
The last thing you need to know in Haskell is the convention which actually gets these things run. That is that, in your Haskell source code, you are supposed to create an IO () (a program whose value doesn't matter) called Main.main, and the Haskell compiler is supposed to take this program which you described, and give it to you as an executable which you can run whenever you want. As a very special case, the GHCi interpreter will notice if you produce an IO x expression at the top level and will immediately run it for you, but that is very different from how the rest of the language works. For the most part, Haskell says, describe the program and I will give it to you.
Now that you know that Haskell has no magic and the Haskell IO x type just is a static representation of a computer program as a value, rather than something which does side-effecting stuff when you "reduce" it (like it is in other languages), we can turn to your getList. Clearly getList :: IO [String] makes the most sense based on what you said: a program which allows a user to build a list from a series of inputs.
Now to build the internals, you've got the right guess: we've got to start with a getLine and either finish off the list or continue accepting inputs, prepending the line to the list:
getList = do
line <- getLine
if line == 'exit' then return []
else fmap (line:) getList
You've also identified another way to do it, which depends on taking a list of strings and producing a new list:
getList :: IO [String]
getList = fmap reverse (go []) where
go xs = do
x <- getLine
if x == "exit" then return xs
else go (x : xs)
There are probably several other ways to do it.

Why can't you map print to a list in Haskell?

I checked this post before making this, but that post doesn't really explain why this doesn't work.
foo :: (Num a, Show a) => a -> IO ()
foo 0 = print "Was zero"
foo x = print x
foo 2 -- prints 2
foo 5 -- prints 5
map foo [0..10] :: [IO ()] -- Doesn't print out numbers.
Edit:
bar 0 = foo 0
bar n = do
foo n
bar (n - 1)
I do understand why this returns [IO ()], but I don't understand why the printing doesn't occur while building this list. At the very least, I'd expect that we'd see the first print call occur because of lazy evaluation.
In the process of creating this list, why isn't the 'side effect' of printing to the screen occurring? Is the foo function not actually entered when applied to each element of the list? If the print calls are evaluated to get the IO () to build the list, why doesn't the side effect happen?
map foo [0..10] will definitely construct a list of IO () values, but constructing an IO () value doesn’t execute the IO. You probably know this intuitively: if we have a global IO () and nothing referencing it, it doesn’t get executed:
sayHello :: IO ()
sayHello = putStrLn "hello"
You might attribute that to laziness; after all, if sayHello isn’t referenced, nothing ever forces its evaluation. But then, this doesn’t do anything either:
main = sayHello `seq` return ()
Here, we are certainly evaluating sayHello, but we’re only evaluating an IO ().
What makes an IO do something is when you compose it into another IO (like main) and that gets run, and only then will it do something:
main = sayHello
I should note that GHCi clouds the situation a bit. GHCi has some special interactions with IO: if the overall expression you type at the prompt yields an IO, it will execute it and display the result of that. Otherwise, it just displays the result. But that is just an interactive feature; in real Haskell code, you can’t just have an IO () and expect it to turn into a () magically.
If the print calls are evaluated to get the IO () to build the list, why doesn't the side effect happen?
Because evaluating an expression of type IO () doesn't have any side effects. In fact, evaluating an expression of any type doesn't have any side effects.
The only way to run an IO action is to assign it to main. Evaluating IO actions does not run them.
If you want to call print on the list of values, you must do two things:
First: use mapM_ to build an IO action that prints each value:
mapM_ print [1..3] :: IO ()
Second, assign that expression to main:
main = mapM_ print [1..3]
If you leave out the second step (assign it to something other than main), nothing will happen.
In the IO monad, something like IO a is required. You have [IO ()] which is a list of IO operations. You can use mapM instead, to do a monadic map. mapM f is equivalent to sequence . map f.

Breaking out of monad sequence

Is it possible to break out of a monad sequence?
For instance, if I want to break out of a sequence earlier based on some condition calculated in the middle of the sequence. Say, in a 'do' notation I bind a value and based on the value I want to either finish the sequence or stop it. Is there something like a 'pass' function?
Thanks.
Directly using if
You could do this directly as Ingo beautifully encapsulated, or equivalently for example
breakOut :: a -> m (Either MyErrorType MyGoodResultType)
breakOut x = do
y <- dosomethingWith x
z <- doSomethingElseWith x y
if isNoGood z then return (Left (someerror z)) else do
w <- process z
v <- munge x y z
u <- fiddleWith w v
return (Right (greatResultsFrom u z))
This is good for simply doing something different based on what values you have.
Using Exceptions in the IO monad
You could use Control.Exception as Michael Litchard correctly pointed out. It has tons of error-handling, control-flow altering stuff in it, and is worth reading if you want to do something complex with this.
This is great if your error production could happen anywhere and your code is complex. You can handle the errors at the top level, or at any level you like. It's very flexible and doesn't mess with your return types. It only works in the IO monad.
import Control.Exception
Really I should roll my own custom type, but I can't be bothered deriving Typable etc, so I'll hack it with the standard error function and a few strings. I feel quite guilty about that.
handleError :: ErrorCall -> IO Int
handleError (ErrorCall msg) = case msg of
"TooBig" -> putStrLn "Error: argument was too big" >> return 10000
"TooSmall" -> putStrLn "Error: argument was too big" >> return 1
"Negative" -> putStrLn "Error: argument was too big" >> return (-1)
"Weird" -> putStrLn "Error: erm, dunno what happened there, sorry." >> return 0
The error handler needs an explicit type to be used in catch. I've flipped the argument to make the do block come last.
exceptOut :: IO Int
exceptOut = flip catch handleError $ do
x <- readLn
if (x < 5) then error "TooSmall" else return ()
y <- readLn
return (50 + x + y)
Monad transformers etc
These are designed to work with any monad, not just IO. They have the same benefits as IO's exceptions, so are officially great, but you need to learn about monad tranformers. Use them if your monad is not IO, and you have complex requirements like I said for Control.Exception.
First, read Gabriel Conzalez's Breaking from a loop for using EitherT to do two different things depending on some condition arising, or MaybeT for just stopping right there in the event of a problem.
If you don't know anything about Monad Transformers, you can start with Martin Grabmüller's Monad Transformers Step by Step. It covers ErrorT. After that read Breaking from a Loop again!
You might also want to read Real World Haskell chapter 19, Error handling.
Call/CC
Continuation Passing Style's callCC is remarkably powerful, but perhaps too powerful, and certainly doesn't produce terribly easy-to-follow code. See this for a fairly positive take, and this for a very negative one.
So what I think you're looking for is the equivalent of return in imperative languages, eg
def do_something
foo
bar
return baz if quux
...
end
Now in haskell this is doesn't work because a monadic chain is just one big function application. We have syntax that makes it look prettier but it could be written as
bind foo (bind bar (bind baz ...)))
and we can't just "stop" applying stuff in the middle. Luckily if you really need it there is an answer from the Cont monad. callCC. This is short for "call with current continuation" and generalizes the notation of returns. If you know Scheme, than this should be familiar.
import Control.Monad.Cont
foo = callCC $ \escape -> do
foo
bar
when baz $ quux >>= escape
...
A runnable example shamelessly stolen from the documentation of Control.Monad.Cont
whatsYourName name =
(`runCont` id) $ do
response <- callCC $ \exit -> do
validateName name exit
return $ "Welcome, " ++ name ++ "!"
return response
validateName name exit = do
when (null name) (exit "You forgot to tell me your name!")
and of course, there is a Cont transformer, ContT (which is absolutely mind bending) that will let you layer this on IO or whatever.
As a sidenote, callCC is a plain old function and completely nonmagical, implementing it is a great challenge
So I suppose there is no way of doing it the way I imagined it originally, which is equivalent of a break function in an imperative loop.
But I still get the same effect below based in Ingo's answer, which is pretty easy (silly me)
doStuff x = if x > 5
then do
t <- getTingFromOutside
doHeavyHalculations t
else return ()
I don't know though how it would work if I need to test 't' in the example above ...
I mean, if I need to test the bound value and make an if decision from there.
You can never break out of a "monad sequence", by definition. Remember that a "monad sequence" is nothing else than one function applied to other values/functions. Even if a "monad sequence" gives you the illusion that you could programme imperative, this is not true (in Haskell)!
The only thing you can do is to return (). This solution of the practical problem has already been named in here. But remember: it gives you only the illusion of being able to break out of the monad!

Resources