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

haskell, io, seq

Solution

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.

Problem

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`?

Original source

Related problems