viraptor
viraptor

Reputation: 34205

Condition in do block

Why does the following block of code:

main = do
    line <- getLine
    if null line
        then runTestTT tests
        else do
            line2 <- getLine
            seq::[Int] <- return $ map read $ words line2
            print $ process seq

throw an error:

lgis.hs:28:13:
    Couldn't match type `()' with `Counts'
    Expected type: IO Counts
      Actual type: IO ()
    In a stmt of a 'do' block: print $ process seq
    In the expression:
      do { line2 <- getLine;
           seq :: [Int] <- return $ map read $ words line2;
           print $ process seq }
    In a stmt of a 'do' block:
      if null line then
          runTestTT tests
      else
          do { line2 <- getLine;
               seq :: [Int] <- return $ map read $ words line2;
               print $ process seq }

Even though both:

main = do
    runTestTT tests

and

main = do
    line <- getLine
    line2 <- getLine
    seq::[Int] <- return $ map read $ words line2
    print $ process seq

work fine?

Upvotes: 3

Views: 240

Answers (1)

Daniel Fischer
Daniel Fischer

Reputation: 183978

Both branches of an if then else must have the same type, but

runTestTT tests :: IO Counts

and

print $ process seq :: IO ()

You can add a return () to the then branch, the modern way to do that is to use Control.Monad.void,

main = do
    line <- getLine
    if null line
        then void (runTestTT tests)         -- formerly: runTestTT tests >> return ()
        else do
            line2 <- getLine
            seq::[Int] <- return $ map read $ words line2
            print $ process seq

to fix it (or you could add a return some_value_of_type_Counts to the else branch).

Upvotes: 9

Related Questions