I'm really really struggling with understanding callCC. I get the power of Continuations and I've been using the concept in some of my projects to create cool concepts. But never have I needed to use something with greater capabilities than cont :: ((a->r)->r)-> Cont r a.
After using it, it makes a lot of sense why they call the Cont Monad the mother of all monads, YET, I don't get when would I need to use callCC, and that's exactly my question.
callCC gives you "early return" semantics, but in a monadic context.
Say you wanted to doOne, and if that returns True, you immediately stop, otherwise you go on to doTwo and doThree:
doOne :: Cont r Bool
doTwo :: Cont r ()
doThree :: Cont r ()
doThings :: Cont r ()
doThings = do
one <- doOne
if one
then pure ()
else do
doTwo
doThree
See that if branching there? One branch is not that bad, could be dealt with, but imagine there are multiple such points where you just want to bail? This gets very ugly very quickly.
With callCC you can have "early return": you bail at the branching point and don't have to nest the rest of the computation:
doThings = callCC \ret -> do
one <- doOne
when one $ ret ()
doTwo
doThree
Much more pleasant to read!
More importantly, since ret here is not a special syntax (like return in C-like languages), but just a value like any other, you can pass it to other functions too! And those functions can then perform what's called "non-local return" - i.e. they can "stop" the doThings computation, even from multiple nested calls deep. For example, I could factor out checking of the doOne's result into a separate function checkOne like this:
checkOne ret = do
one <- doOne
when one $ ret ()
doThings = callCC \ret -> do
checkOne ret
doTwo
doThree
Related
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.
I'm relatively new to Polysemy, and I'm trying to wrap my head around how to use NonDet correctly. Specifically, let's say I've got this computation
generate :: Member NonDet r => Sem r Int
generate = msum $ fmap pure [0..]
computation :: (Member NonDet r, Member (Final IO) r) => Sem r ()
computation = do
n <- generate
guard (n == 100)
embedFinal $ print n
It's a horribly inefficient way to print the number 100, but it demonstrates the problem I'm having. Now, I want to run this effect only insofar as to get the first success. That is, I want to run this effect long enough to "find" the number 100 and print it, and then I want to stop.
My first attempt
attempt1 :: IO ()
attempt1 = void . runFinal . runNonDet #[] $ computation
This one fails to short-circuit. It prints 100 but then hangs forever, looking for the number 100 again. That makes sense; after all, I didn't actually tell it I only wanted one solution. So let's try that.
My second attempt
runNonDetOnce :: Sem (NonDet ': r) a -> Sem r (Maybe a)
runNonDetOnce = fmap listToMaybe . runNonDet
attempt2 :: IO ()
attempt2 = void . runFinal . runNonDetOnce $ computation
All we're doing here is discarding all but the head of the list. Understandably, this didn't change anything. Haskell already wasn't evaluating the list, so discarding an unused value changes nothing. Like attempt1, this solution hangs forever after printing 100.
My third attempt
attempt3 :: IO ()
attempt3 = void . runFinal . runNonDetMaybe $ computation
So I tried using runNonDetMaybe. This one, unfortunately, just exits without printing anything. Figuring out why that is took a bit, but I have a theory. The documentation says
Unlike runNonDet, uses of <|> will not execute the second branch at all if the first option succeeds.
So it's greedy and doesn't backtrack after success, basically. Thus, it runs my computation like this.
computation = do
n <- generate -- Ah yes, n = 0. Excellent!
guard (n == 100) -- Wait, 0 /= 100! Failure! We can't backtrack, so abort.
embedFinal $ print n
Non-Solutions
In this small example, we could just alter the computation a bit, like so
computation :: (Member NonDet r, Member (Final IO) r) => Sem r ()
computation = msum $ fmap (\n -> guard (n == 100) >> embedFinal (print n)) [0..]
So rather than generate a number and then check it later, we simply move generate inside of computation. With this computation, attempt3 succeeds, since we can get to the "correct" answer without backtracking. This works in this small example, but it's infeasible for a larger codebase. Unless someone has a good systematic way of avoiding backtracking, I don't see a good way to generalize this solution to computations that span over multiple files in a large program.
The other non-solution is to cheat using IO.
computation :: (Member NonDet r, Member (Final IO) r) => Sem r ()
computation = do
n <- generate
guard (n == 100)
embedFinal $ print n
embedFinal $ exitSuccess
Now attempt1 and attempt2 succeed, since we simply forcibly exit the program after success. But, aside from feeling incredibly sloppy, this doesn't generalize either. I want to stop running the current computation after finding 100, not the whole program.
So, to summarize, I want the computation given in the first code snippet above to be run using Polysemy in some way that causes it to backtrack (in NonDet) until it finds one successful value (in the example above, n = 100) and then stop running side effects and end the computation. I tried delving into the source code of runNonDetMaybe and co in this hopes of being able to reproduce something similar to it that has the effect I want, but my Polysemy skills are not nearly to the level of understanding all of the Weaving and decomp shenanigans happening there. I hope someone here who has more expertise with this library than I do can point me in the right direction to running NonDet with the desired effects.
Now attempt1 and attempt2 succeed, since we simply forcibly exit the program after success. But, aside from feeling incredibly sloppy, this doesn't generalize either. I want to stop running the current computation after finding 100, not the whole program.
Rather than exitSuccess, a closely related idea is to throw an exception that you can catch in the interpreter.
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!
I thought that in principle Haskell's type system would forbid calls to impure functions (i.e. f :: a -> IO b) from pure ones, but today I realized that by calling them with return they compile just fine. In this example:
h :: Maybe ()
h = do
return $ putStrLn "???"
return ()
h works in the Maybe monad, but it's a pure function nevertheless. Compiling and running it simply returns Just () as one would expect, without actually doing any I/O. I think Haskell's laziness puts the things together (i.e. putStrLn's return value is not used - and can't since its value constructors are hidden and I can't pattern match against it), but why is this code legal? Are there any other reasons that makes this allowed?
As a bonus, related question: in general, is it possible to forbid at all the execution of actions of a monad from within other ones, and how?
IO actions are first-class values like any other; that's what makes Haskell's IO so expressive, allowing you to build higher-order control structures (like mapM_) from scratch. Laziness isn't relevant here,1 it's just that you're not actually executing the action. You're just constructing the value Just (putStrLn "???"), then throwing it away.
putStrLn "???" existing doesn't cause a line to be printed to the screen. By itself, putStrLn "???" is just a description of some IO that could be done to cause a line to be printed to the screen. The only execution that happens is executing main, which you constructed from other IO actions, or whatever actions you type into GHCi. For more information, see the introduction to IO.
Indeed, it's perfectly conceivable that you might want to juggle about IO actions inside Maybe; imagine a function String -> Maybe (IO ()), which checks the string for validity, and if it's valid, returns an IO action to print some information derived from the string. This is possible precisely because of Haskell's first-class IO actions.
But a monad has no ability to execute the actions of another monad unless you give it that ability.
1 Indeed, h = putStrLn "???" `seq` return () doesn't cause any IO to be performed either, even though it forces the evaluation of putStrLn "???".
Let's desugar!
h = do return (putStrLn "???"); return ()
-- rewrite (do foo; bar) as (foo >> do bar)
h = return (putStrLn "???") >> do return ()
-- redundant do
h = return (putStrLn "???") >> return ()
-- return for Maybe = Just
h = Just (putStrLn "???") >> Just ()
-- replace (foo >> bar) with its definition, (foo >>= (\_ -> bar))
h = Just (putStrLn "???") >>= (\_ -> Just ())
Now, what happens when you evaluate h?* Well, for Maybe,
(Just x) >>= f = f x
Nothing >>= f = Nothing
So we pattern match the first case
f x
-- x = (putStrLn "???"), f = (\_ -> Just ())
(\_ -> Just ()) (putStrLn "???")
-- apply the argument and ignore it
Just ()
Notice how we never had to perform putStrLn "???" in order to evaluate this expression.
*n.b. It is somewhat unclear at which point "desugaring" stops and "evaluation" begins. It depends on your compiler's inlining decisions. Pure computations could be evaluated entirely at compile time.
Consider the fragment -
getLine >>= \_ -> getLine >>= putStr
It does the reasonable thing, asking for a string twice, and then printing the last input. Because the compiler has no way of knowing what outside effects getLine has, it has to execute both of them, even though we throw away the result of the first one.
What I need is to wrap the IO Monad into another Monad (M) that allows IO computations to be effectively NOPs unless their return values are used. So that the program above could be rewritten as something like -
runM $ lift getLine >>= \_ -> lift getLine >>= lift putStr
Where
runM :: M a -> IO a
lift :: IO a -> M a
And the user is asked for input only once.
However, I cannot figure out how to write this Monad to achieve the effect I want. I'm not sure if it's even possible. Could someone please help?
Lazy IO is usually implemented using unsafeInterleaveIO :: IO a -> IO a, which delays the side effects of an IO action until its result is demanded, so we'll probably have to use that, but let's get some minor problems out of the way first.
First of all, lift putStr would not type check, as putStr has type String -> IO (), and lift has type IO a -> M a. We'll have to use something like lift . putStr instead.
Secondly, we're going to have to differentiate between IO actions that should be lazy and those who should not. Otherwise the putStr will never be executed, as we're not using it's return value () anywhere.
Taking that into account, this seems to work for your simple example, at least.
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
import System.IO.Unsafe
newtype M a = M { runM :: IO a }
deriving (Monad)
lazy :: IO a -> M a
lazy = M . unsafeInterleaveIO
lift :: IO a -> M a
lift = M
main = runM $ lazy getLine >> lazy getLine >>= lift . putStr
However, as C. A. McCann points out, you should probably not use this for anything serious. Lazy IO is frowned upon already, as it makes it difficult to reason about the actual order of the side effects. This would make it even harder.
Consider this example
main = runM $ do
foo <- lazy readLn
bar <- lazy readLn
return $ foo / bar
The order of the two numbers are read in will be completely undefined, and may change depending on compiler version, optimizations or the alignment of the stars. The name unsafeInterleaveIO is long and ugly for a good reason: to remind you of the dangers of using it. It's a good idea to let people know when it's being used and not hide it in a monad.
There's no sensible way to do this, because to be quite honest it's not really a sensible thing to do. The entire purpose for introducing monadic I/O was to give a well-defined ordering to effects in the presence of lazy evaluation. It is certainly possible to throw that out the window if you really must, but I'm not sure what actual problem this would solve other than making it easier to write confusingly buggy code.
That said, introducing this sort of thing in a controlled fashion is what "Lazy IO" already does. The "primitive" operation for that is unsafeInterleaveIO, which is implemented roughly as return . unsafePerformIO, plus some details to make things behave a bit nicer. Applying unsafeInterleaveIO to everything, by hiding it in the bind operation of your "lazy IO" monad, would probably accomplish the ill-advised notion you're after.
What you are looking for isn't really a monad, unless you want to work with unsafe stuff like unsafeInterleaveIO.
Instead, a much cleaner abstraction here is Arrow.
I think, the following could work:
data Promise m a
= Done a
| Thunk (m a)
newtype Lazy m a b =
Lazy { getLazy :: Promise m a -> m (Promise m b) }