Home > Blockchain >  Parse error after read function in Haskell
Parse error after read function in Haskell

Time:11-08

I currently am creating a program that takes a number from a user and then decides what happens based off the input:

function :: Int -> IO ()
function n = do
            putStr "Input: "
            x <- getLine
            let y = (read x :: Int)
            if y == n
                then
                    print "Something"
            else if y < n 
                then
                    print "Something"
                    function n
            else if y > n
                then
                    print "Something"
                    function n

However, the code above returns a 'parse error (possibly incorrect indentation or mismatched brackets)' error. This error seems to occur when I put any sort of conditional statement (if/guard/case) after the let guess = (read x :: Int) line and I cannot figure out why. Any suggestions would be much appreciated, thanks in advance.

CodePudding user response:

The problem are then blocks that contain multiple lines. For these you can use additional dos to perform desugaring. Another problem is that each if … then … else … needs an else … clause, since these are expressions, there are no statements:

function :: Int -> IO ()
function n = do
    putStr "Input: "
    x <- getLine
    let y = (read x :: Int)
    if y == n
        then
            print "Something"
    else if y < n 
        then do
            print "Something"
            function n
    else if y > n
        then do
            print "Something"
            function n
    else
        pure ()

simpler is:

function :: Int -> IO ()
function n = do
    putStr "Input: "
    x <- getLine
    let y = read x
    if y == n then print "Something"
    else if y < n then print "Something" >> function n
    else if y > n then print "Something" >> function n
    else pure ()

Normally for two items, it holds that x < y, x > y or x == y (although for Doubles for example that does not hold). You thus can omit the last check:

function :: Int -> IO ()
function n = do
    putStr "Input: "
    x <- getLine
    let y = read x
    if y == n then print "Something"
    else if y < n then print "Something" >> function n
    else print "Something" >> function n

We can also work with a multi-way if:

{-# LANGUAGE MultiWayIf #-}

function :: Int -> IO ()
function n = do
    putStr "Input: "
    x <- getLine
    let y = read x
    if
      | y == n -> print "Something"
      | y < n -> print "Something" >> function n
      | otherwise -> print "Something" >> function n

or with a case … of …:

function :: Int -> IO ()
function n = do
    putStr "Input: "
    x <- getLine
    case read x `compare` n of
      EQ -> print "Something"
      LT -> print "Something" >> function n
      GT -> print "Something" >> function n
  • Related