t4ccer
t4ccer

Reputation: 83

Forcing IO to evaluate

I need some wrapped on IO type, but I can not 'force' haskell to run IO action in wrapper. I tried using bang pattern for it, but it also does not work.

I recreated problem on much simpler type. Code snippet below

{-# LANGUAGE BangPatterns #-}

newtype IOWrapper a = IOWrapper (IO a) 

mkWrapper :: IO a -> IOWrapper a
mkWrapper !a = IOWrapper a

foo :: IO ()
foo = putStrLn "foo" --Shows "foo" on console, as expected

bar :: IOWrapper ()
bar = IOWrapper $ putStrLn "bar" --Shows nothing

baz :: IOWrapper ()
baz = mkWrapper $ putStrLn "baz" --Shows nothing

Upvotes: 1

Views: 285

Answers (2)

Fyodor Soikin
Fyodor Soikin

Reputation: 80805

Merely calling putStrLn "foo" does not actually print "foo". Instead, it creates an "action", which then has to be separately "executed", and only then will it print "foo". Moreover, you can actually "execute" it multiple times, and the effect will be produced multiple times as well.

And the only way to "execute" an IO action is to make it the entry point - i.e. the main function - or part of the entry point, or part of another function, which is itself part of the entry point, and so on. The entry point is the root of all effects, there is no effect execution outside of it.

Your foo function probably appears to "work" because you're running it in GHCi, right? If so, then it's executed as part of GHCi's own entry point. GHCi recognizes things of IO type and executes them right away.

But GHCi does not recognize things of the IOWrapper type, so it doesn't unwrap and execute them.

So the only way for you to go is to unwrap and execute yourself:

runIOWrapper :: IOWrapper a -> IO a
runIOWrapper (IOWrapper a) = a

Then you can run your wrapped actions in GHCi like this:

> runIOWrapper bar
bar

> runIOWrapper baz
baz

Upvotes: 6

amalloy
amalloy

Reputation: 92117

You cannot do this (without cheating). Evaluating IO does not cause it to perform its effects. The only thing that causes IO to perform effects is to include it in the special action main :: IO a, usually by combining a number of smaller actions into one large IO action.

Instead of asking how to do this thing, back up and think about why you want to do it. Ask instead how to accomplish your original goal.

Upvotes: 5

Related Questions