Haskell IF Else
Asked Answered
S

3

5
input <- readLn
 if (input == 0)
 then 
  putStr  "0" 
 else if (input ==1)
then 
  putStr  "1" 
else if (input ==2)

in this kind of senario how to use multiple putStr with in a then or else if ?

when i try getting a error

Type error in application
*** Expression     : putStr "0" putStr "0"
*** Term           : putStr
*** Type           : String -> IO ()
*** Does not match : a -> b -> c -> d
Safranine answered 8/6, 2011 at 18:53 Comment(2)
This doesn't answer your question, but I hope you realize this would be better written as a pattern match. case input of 0 -> … 1 -> …Touchdown
@Touchdown IO with pattern matching is it possible becouse its a IO ProgrammeSafranine
L
9

Use do-notation:

do
  a <- something
  if a 
  then
    do
      cmd1
      cmd2
  else
    do
      cmd3
      cmd4
  cmd5 -- this comes after the 'then' and the 'else'
Lichtenfeld answered 8/6, 2011 at 19:0 Comment(3)
I prefer putting the do on the same line together with the else and then.Ehrman
@FUZxxl Right, me too. But I wanted to emphasize that it's not some magical then do syntax. It's just the normal do-notation inside the branches of the if-then-else expression.Lichtenfeld
i was only using do in starting of the class .. this approach solved problemSafranine
E
6

The canonical explanation for this is that you want to form a new monadic value out of two existing ones. Let's look at the type of putStr,

IO ()

That means it's some black box, that when executed, will "return" the (one-and-only) value of unit type. The key idea behind monadic computation is that you have a combinator >>= which will put together two monadic expressions, feeding the result of one into the next (more accurately, a function that creates the next). One critical point is that the IO library provides this combinator, meaning that,

  • It [IO in this case] could skip the second monadic value, for example when the first one throws an exception.
  • It can pass other data around, in the case of IO a RealWorld state containing open file handles, etc.
  • It can "ensure" that the first one evaluates first, unlike most lambda expression evaluations, where the outermost ("last") terms are expanded first. This is important for print, where the first print needs to change the world first.

In your case, use it like this,

putStr "0" >>= (\c -> putStr "0")

There's a shortcut, of course,

putStr "0" >> putStr "0"

and the do-notation, as mentioned by another poster, which is yet more syntax sugar,

do
    putStr "0"
    putStr "0"
Eringo answered 8/6, 2011 at 19:19 Comment(5)
Minor quibble about terminology: The word "monad", used as a noun with no other qualifiers, generally refers only to type constructors that have an instance of Monad. Values of some type m a where m is a monad are generally called something else.Jackscrew
@camccann, regarding terminology: I've seen "commands" and "actions". As in "putStr s is an IO action that prints the string s".Lichtenfeld
@Lambdageek: That's good for IO and some others, but sounds silly applied to something like lists. Variations on something like "monadic value" seems to be used in the general case, but that's very clumsy.Jackscrew
I like "monadic value" better than "action". I'll edit the entry when we're in agreeance.Eringo
@gatoatigrado: Alas, if there was a good general-purpose term in common use I would have said so in the first place. I'd suggest either "action" for IO specifically or something awkward like "monadic value" or "value in the monad" in general. But just "monad" is liable to create confusion. I do recall someone suggesting "mote", which is very cute but I don't think it caught on. :)Jackscrew
T
5

For this contrived example, you may as well use a case, like this:

main = readLn >>= \input -> case input of
    0 ->    putStrLn "0"

    1 ->    putStrLn "0"

    2 ->    putStr   "0" 
         >> putStrLn "0"

    3 ->    putStr   "0"
         >> putStr   "0"
         >> putStrLn "0"

    _ ->    putStrLn "infinite"

This could be perhaps be more readable with do syntax, but I wanted to show it without do syntax first, just to emphasize that do-syntax is just syntax and doesn't actually do anything special. Here it is with do-syntax.

main = do
    input <- readLn
    case input of
        0 -> putStrLn "0"

        1 -> putStrLn "0"

        2 -> do putStr   "0" 
                putStrLn "0"

        3 -> do putStr   "0"
                putStr   "0"
                putStrLn "0"

        _ -> putStrLn "infinite"
Trolly answered 8/6, 2011 at 19:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.