Home > Enterprise >  How to have multiply lines in a case statement in Haskell?
How to have multiply lines in a case statement in Haskell?

Time:10-11

I'm coding in Haskell for the first time, and I'm having trouble with case statements.

points = do
  pts <- try(readLn :: IO Int) :: IO (Either SomeException Int)
  case pts of
    Left ex -> putStrLn "Please enter a number."
    Right val -> return pts

This code is for reading an integer from user input, and checking to make sure it is indeed an int. The issue I'm having is with the Left ex case. What I want to do is, if there's an exception, to print the line "Please enter a number." and then run the points function again. The issue is that I can't figure out how to call points within the Left ex case, as it interferes with the print statement. Any guidance?

CodePudding user response:

You can use the do notation, which allows to glue several IO (or another monad's) actions in order, like you're already doing in the body of points itself:

points = do
  pts <- try(readLn :: IO Int) :: IO (Either SomeException Int)
  case pts of
    Left ex -> do
      putStrLn "Please enter a number."
      points
    Right val -> return pts

Alternatively, you could do what the do notation does under the hood, and use the >>= operator, which is what glues two IO actions in order:

points = do
  pts <- try(readLn :: IO Int) :: IO (Either SomeException Int)
  case pts of
    Left ex -> putStrLn "Please enter a number." >>= \_ -> points
    Right val -> return pts

Note that the \_ -> bit ignores the first action's return value. So you can use the >> operator, which does the same thing as >>=, but throws away the first action's result:

points = do
  pts <- try(readLn :: IO Int) :: IO (Either SomeException Int)
  case pts of
    Left ex -> putStrLn "Please enter a number." >> points
    Right val -> return pts
  • Related