I'm learning Haskell in the hope that it will help me get closer to functional programming. Previously, I've mostly used languages with C-like syntax, like C, Java, and D.
I have a little question about the coding style of an if/else control block used by the tutorial on Wikibooks. The code looks like the following:
doGuessing num = do
putStrLn "Enter your guess:"
guess <- getLine
if (read guess) < num
then do putStrLn "Too low!"
doGuessing num
else if (read guess) > num
then do putStrLn "Too high!"
doGuessing num
else do putStrLn "You Win!"
It makes me confused, because this coding style totally violates the recommended style in C-like languages, where we should indent if, else if, and else at the same column.
I know it just does not work in Haskell, because it would be a parse error if I indented else at the same column as if.
But what about the following style? I think it is much more clear than the above one. But since the above is used by Wikibooks and Yet Another Haskell Tutorial, which is marked "best tutorial available online" at the official Haskell website, I'm not sure whether this coding style is a convention in Haskell programs.
doGuessing num = do
putStrLn "Enter your guess:"
guess <- getLine
if (read guess) < num then
do
putStrLn "Too low!"
doGuessing num
else if (read guess) > num then do
putStrLn "Too high!"
doGuessing num
else do
putStrLn "You Win!"
So, I'm curious about which coding style is used more often—or is there another coding style for this piece of code?
Haskell style is functional, not imperative! Rather than "do this then that," think about combining functions and describing what your program will do, not how.
In the game, your program asks the user for a guess. A correct guess is a winner. Otherwise, the user tries again. The game continues until the user guesses correctly, so we write that:
main = untilM (isCorrect 42) (read `liftM` getLine)
This uses a combinator that repeatedly runs an action (getLine pulls a line of input and read converts that string to an integer in this case) and checks its result:
untilM :: Monad m => (a -> m Bool) -> m a -> m ()
untilM p a = do
x <- a
done <- p x
if done
then return ()
else untilM p a
The predicate (partially applied in main) checks the guess against the correct value and responds accordingly:
isCorrect :: Int -> Int -> IO Bool
isCorrect num guess =
case compare num guess of
EQ -> putStrLn "You Win!" >> return True
LT -> putStrLn "Too high!" >> return False
GT -> putStrLn "Too low!" >> return False
The action to be run until the player guesses correctly is
read `liftM` getLine
Why not keep it simple and just compose the two functions?
*Main> :type read . getLine
<interactive>:1:7:
Couldn't match expected type `a -> String'
against inferred type `IO String'
In the second argument of `(.)', namely `getLine'
In the expression: read . getLine
The type of getLine is IO String, but read wants a pure String.
The function liftM from Control.Monad takes a pure function and “lifts” it into a monad. The type of the expression tells us a great deal about what it does:
*Main> :type read `liftM` getLine
read `liftM` getLine :: (Read a) => IO a
It's an I/O action that when run gives us back a value converted with read, an Int in our case. Recall that readLine is an I/O action that yields String values, so you can think of liftM as allowing us to apply read “inside” the IO monad.
Sample game:
1
Too low!
100
Too high!
42
You Win!
You can use the "case"-construct:
doGuessing num = do
putStrLn "Enter your guess:"
guess <- getLine
case (read guess) of
g | g < num -> do
putStrLn "Too low!"
doGuessing num
g | g > num -> do
putStrLn "Too high!"
doGuessing num
otherwise -> do
putStrLn "You Win!"
A minor improvement to mattiast's case statement (I'd edit, but I lack the karma) is to use the compare function, which returns one of three values, LT, GT, or EQ:
doGuessing num = do
putStrLn "Enter your guess:"
guess <- getLine
case (read guess) `compare` num of
LT -> do putStrLn "Too low!"
doGuessing num
GT -> do putStrLn "Too high!"
doGuessing num
EQ -> putStrLn "You Win!"
I really like these Haskell questions, and I'd encourage others to post more. Often you feel like there's got to be a better way to express what you're thinking, but Haskell is initially so foreign that nothing will come to mind.
Bonus question for the Haskell journyman: what's the type of doGuessing?
The way Haskell interprets if ... then ... else within a do block is very much in keeping with the whole of Haskell's syntax.
But many people prefer a slightly different syntax, permitting then and else to appear at the same indentation level as the corresponding if. Therefore, GHC comes with an opt-in language extension called DoAndIfThenElse, which permits this syntax.
The DoAndIfThenElse extension is made into part of the core language in the latest revision of the Haskell specification, Haskell 2010.
Note that the fact that you have to indent the 'then' and 'else' inside a 'do' block is considered a bug by many. It will probably be fixed in Haskell' (Haskell prime), the next version of the Haskell specification.
You can also use explicit grouping with curly braces. See the layout section of http://www.haskell.org/tutorial/patterns.html
I wouldn't recommend that though. I've never seen anyone use explicit grouping besides in a few special cases. I usually look at the Standard Prelude code for examples of style.
I use a coding style like your example from Wikibooks. Sure, it doesn't follow the C guidelines, but Haskell's not C, and it's fairly readable, especially once you get used to it. It's also patterned after the style of algorithms used in many textbooks, like Cormen.
You will see a bunch of different indentation styles for Haskell. Most of them are very hard to maintain without an editor that is set up to indent exactly in whatever style.
The style you display is much simpler and less demanding of the editor, and I think you should stick with it. The only inconsistency I can see is that you put the first do on its own line while you put the other dos after the then/else.
Heed the other advice about how to think about code in Haskell, but stick to your indentation style.
Related
I want to write a function which, when called, will relentlessly ask for user input until the input can be read as an integer, (at which point the integer is returned to a possible do block where the function was called in the first place)
My code here:
lp_reqInt =
do
input1 <- getLine
if ((readMaybe input1 :: Maybe Int) == Nothing)
then do
putStrLn "(integer input required, please try again)"
lp_reqInt
else let output = fromMaybe (-666) (readMaybe input1 :: Maybe Int)
return output
trying to compile this gives the suspiciously simple error of parse error (possibly incorrect indentation or mismatched brackets) for the last line. (No indent characters were used throughout the whole file)
How should I change my code to have the intended behaviour? Is that even possible?
The other answer discusses what was wrong, and the minimal fix. In addition to the minimal thing that will get you moving on with your code, I thought it might also be interesting to show the idiomatic fix, namely, to use pattern matching instead of if. So:
lp_reqInt :: IO Int
lp_reqInt = do
input1 <- getLine
case readMaybe input1 of
Nothing -> do
putStrLn "(integer input required, please try again)"
lp_reqInt
Just n -> return n
This doesn't require the use of the weird fall-back -666 in fromMaybe, which is nice. Using pattern matching instead of (==) also has a more subtle advantage: it doesn't require the underlying type to have an Eq instance. For Int there is one, so there's no advantage in this code, but in other situations it can matter more. I've also lifted the type signature to the top-level; see here for further discussion of this idiom.
You seem to be slightly misunderstanding how do-notation works.
I'll give you a 'correct' version and we can work off that:
lp_reqInt = do
input1 <- getLine
let maybeInput = readMaybe input1 :: Maybe Int
if maybeInput == Nothing
then do putStrLn "(integer input required, please try again)"
lp_reqInt
else return $ (\(Just x) -> x) maybeInput
Note the let-statement at the top there. I can do a let-statement rather than a let-in-statement here, because it is in the top level of a do-block. When you wrote let output = fromMaybe (...), that was not in the top level of a do-block, that was in the second part of an if-statement, hence it will not work.
You were getting a parse error for this very reason: GHC expected an accompanying in!
Previous answers are great but i just would like to extend this topic with another reasonable approach for those who end up here searching not exactly what the OP is asking for but something relevant.
Since the topic mentions User Input (IO) and Integer (Maybe Int) we end up with a type like IO (Maybe Int). Such types are best expressed under the Monad Transformers, namely MaybeT IO Int and they act nicely as Alternative class members as well.
Haskell has fantastic solutions for these cases such that we may approach the same problem like;
import Control.Monad (msum)
import Control.Monad.Trans.Maybe
import Control.Monad.Trans (lift)
import Text.Read (readMaybe)
lp_reqInt :: MaybeT IO Int
lp_reqInt = msum . repeat $ (lift . putStrLn) "Enter an integer.." >>
(MaybeT $ readMaybe <$> getLine)
It's relentless :)
λ> runMaybeT lp_reqInt
Enter an integer..
boru
Enter an integer..
not an integer
Enter an integer..
42
Just 42
An example from Wikibooks (http://en.wikibooks.org/wiki/Haskell/Simple_input_and_output)
doGuessing num = do
putStrLn "Enter your guess:"
guess <- getLine
if (read guess) < num
then do putStrLn "Too low!"
doGuessing num
else if (read guess) > num
then do putStrLn "Too high!"
doGuessing num
else putStrLn "You Win!"
Wikibooks says 'doGuessing num' has type IO () in the outer "then" branch.
do putStrLn "Too low!"
doGuessing num
I don't understand why 'doGuessing num' has type IO (), and just guess this is because:
1)the last "else" brance (putStrLn "You Win!") has type IO ().
2)in Haskell, "then" branch and the "else" branch have the same type.
3)the final action (putStrLn "You Win!") defines the type of the whole do block.
so 'doGuessing num' has type IO ().
I am not sure my understanding is right. Actions is new for me, please correct me if I am wrong.
Essentially, all of that. In this example, there's a whole bunch of ways in which Haskell can infer the type.
(In addition to what you said: all actions in a do block must be in the same monad; the first putStrLn "Enter your guess: " already gives you that doGuessing is in the IO monad (i.e. IO a for some yet unknown a. The () yielded by the putStrLn is not relevant here).The same goes for guess <- getLine, this is also an IO action.)
The great thing about a Hindley-Milner type system such as Haskell is that there is not a single “route” for how type information travels through the code. It's not that type information is in some way attached to values, like in a dynamic language. (The kind of type inference that C++ or Java uses is basically a “pre-simulation” of that dynamic-type flow.)
Rather, the compiler gathers all information it can find, anywhere, and combines it to infer the type of the whole expression. As musically_ut already remarked in the comments, this is done through type unification.
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!
If I've got a function that returns IO Bool (specifically an atomically), is there any way to use the return value directly in the if statement, without binding?
So currently I've got
ok <- atomically $ do
...
if (ok) then do
...
else do
...
Is it at all possible to write this as something like
if (*some_operator_here* atomically $ do
...) then do
...
else do
...
I was hoping there'd be a way to use something like <- anonymously, i.e., if (<- atomically ...) but so far no such luck.
Similarly on getLine, is it possible to write something like
if ((*operator* getLine) == "1234") then do ...
Related addendum--what is the type of (<-)? I can't get it to show up in ghci. I'm assuming it's m a -> a, but then that would mean it could be used outside of a monad to escape that monad, which would be unsafe, right? Is (<-) not a function at all?
You can use ifM from Control.Conditional if that suits your purpose and its not even hard to write a similar function.
Just to give you example
import Control.Conditional
import Control.Monad
(==:) :: ( Eq a,Monad m) => m a -> m a -> m Bool
(==:) = liftM2 (==)
main = ifM (getLine ==: getLine) (print "hit") (print "miss")
I think there are ways using rebindable syntax extension that you can even use if c then e1 else e2 like syntax for ifM but it is not worth the effort to try that.
With GHC 7.6 and the LambdaCase language extension, you can write
{-# LANGUAGE LambdaCase #-}
import System.Directory
main = do
doesFileExist "/etc/passwd" >>= \case
True -> putStrLn "Yes"
False -> putStrLn "No"
It is not exactly if..then..else, but closer enough, does not require binding to the result, and some people (not me) say that if..then..else is bad style in Haskell anyways.
No, you cannot. Well, to be honest, there is a 'hack' that will allow you to at least write code like this and get it to compile, but the results will almost certainly not be what you wanted or expected.
Why is this not possible? Well, for one thing a value of type IO Bool does not in any sense contain a value of type Bool. Rather it is an 'action' that when performed will return a value of type Bool. For another thing, if this were possible, it would allow you to hide side-effects inside what appears to be pure code. This would violate a core principal of Haskell. And Haskell is very principled.
I've been attempting to learn Haskell independently in the last few weeks. Currently, I'm trying to implement a goofy little guessing game where the computer chooses a random number and the user tries to guess it. If the user is wrong, the program tells the user either that the answer is higher or lower and allows the user to guess until they guess correctly. I've got it working, but I would like to add the ability to keep track of the number of guesses that the user makes every game and report that number to the user once they guess correctly.
Coming from an imperative background, the natural thing to do would be to have a counter that is incremented every time the user makes a guess, but you can't really do that in Haskell (at least it seems like the statelessness and immutability of everything would prevent that).
I toyed with the idea of making the getGuess and giveHints functions take an extra parameter that represents the number of guesses so far (let's call it numGuesses), and, on every call to those methods, pass (numGuesses+1). But I couldn't get that to work (not to mention I don't even know if that would work).
My code is below. Any suggestions would be really appreciated. I'm mostly looking for ideas, but feel free to post actual code as well. Also, feel free to let me know if my code sucks and how I could improve it if you notice anything heinous (I've only been programming functionally for a couple weeks!)
import System.Random
import System.IO
import Control.Monad
main = do
gen <- getStdGen
let (ans,_) = randomR (1,100) gen :: (Int,StdGen)
putStrLn $ "I'm thinking of a number between 1 and 100..."
getGuess ans
putStrLn "You guessed it in __ guesses!"
putStr "Play again? "
hFlush stdout
desire <- getLine
when ((desire !! 0) `elem` ['y','Y']) $ do
putStrLn ""
newStdGen
main
getGuess ans = do
putStr "Your guess? "
hFlush stdout
guessStr <- getLine
giveHints ans (read guessStr)
giveHints ans guess = do
when (ans /= guess) $ do
if ans > guess
then putStrLn "It's higher."
else putStrLn "It's lower."
getGuess ans
Note: I am using hFlush stdout because I'm using line buffering and, without it, the order of some of the interactions are not what one would expect.
You can in fact implement the counting method you were thinking about, but you still have to pass the state around explicitly. But in this case, it isn't much of a hassle at all. In fact, this is a pattern that one sees pretty often for helper functions, where actually using the State monad would be overkill.
The pattern I'm referring to often looks like this:
doStuff xs' = go xs' 0
where
go (x:xs) n = .. etc ..
Here's the code.
import System.Random (randomRIO)
import Control.Applicative ((<$>))
import Control.Monad (when)
import Text.Printf (printf)
playGame :: Int -> Int -> IO ()
playGame answer curGuesses = do
putStrLn "What is your guess?"
putStr ">"
guess <- getGuessFromUser
when (guess /= answer) $ do
giveHints answer guess
playGame answer (curGuesses + 1)
when (guess == answer) $ do
putStrLn "You guessed it!"
printf "You guessed %d times!\n" (curGuesses + 1)
giveHints :: Int -> Int -> IO ()
giveHints answer guess
| answer > guess = putStrLn "It's higher!"
| otherwise = putStrLn "It's lower!"
getGuessFromUser :: IO Int
getGuessFromUser = do
read <$> getLine
main :: IO ()
main = do
answer <- randomRIO (1, 100)
putStrLn "I'm thinking of a number between 1 and 100."
playGame answer 0
Notes
<$> is fmap
I used randomRIO as Daniel mentioned, since we're already in the IO monad.
I did not have to use hSetBuffering or hFlush using the command prompt on Windows to get correct output. YMMV, however.
Adding an extra parameter for the number of guesses is exactly how you do this sort of thing functionally.
The basic functional mode of thinking is that if you have a function that needs to behave differently depending on different values of "something", then that something is a parameter to the function. This is a simple consequence of purity; a function must always return the same thing for the same inputs.
When you get to more advanced techniques there are various ways of "hiding" the extra parameters to free you up from having to write/pass them explicitly; this is basically exactly what the State monad does, and one way of thinking about the IO monad is that it's doing something similar. But while you're new to functional programming it's probably more helpful to get used to this mode of thinking; you communicate information to a function you're calling through its arguments, and receive information back through its arguments. You can't resort to the imperative trick of just leaving information in some external place (e.g. the value of a counter) where you know the function you call will look for it (or even modify it).