Search code examples
haskelltype-mismatchdo-notation

Type mismatches in Haskell `do` with multiple return values


I have the following code, but on compile I am getting several errors. Can I return two variables as a tuple from a do statement?

Couldn't match type ‘[]’ with ‘(,) String’
      Expected type: (String, Char)
        Actual type: String
    • In a stmt of a 'do' block: f <- string_prog (g)

Couldn't match expected type ‘(String, t0)’
                  with actual type ‘Int’
    • In a stmt of a 'do' block: tx <- mult_prog x y

Couldn't match expected type ‘t0 -> Int’ with actual type ‘Char’
    • The function ‘f’ is applied to one argument,
      but its type ‘Char’ has none
    mult_prog :: Int -> Int -> Int
    mult_prog one1 one2 = one1 * one2
                            
    string_prog :: String -> String
    string_prog s = ("  " ++ s ++ "   ")     
    
    
    do_prog :: String -> Int -> Int -> (String, Int)
    
    do_prog g x y =   do f <- string_prog(g)  
    
                         tx <- mult_prog x y
    
                         return $ f tx 

Solution

  • <- is for "extracting" values from monads, which your values aren't (not in the way you think they are at least). return is for wrapping a value in a monad, which your return value isn't. Instead, use let and just have a tuple as the final value:

    mult_prog :: Int -> Int -> Int
    mult_prog one1 one2 = one1 * one2
                            
    string_prog :: String -> String
    string_prog s = ("  " ++ s ++ "   ")     
    
    
    do_prog :: String -> Int -> Int -> (String, Int)
    do_prog g x y = do let f = string_prog g
                       let tx = mult_prog x y
                       (f, tx)
    

    Note that you don't even need do and you can just use let...in:

    mult_prog :: Int -> Int -> Int
    mult_prog one1 one2 = one1 * one2
                            
    string_prog :: String -> String
    string_prog s = ("  " ++ s ++ "   ")     
    
    
    do_prog :: String -> Int -> Int -> (String, Int)
    do_prog g x y = let f = string_prog g
                        tx = mult_prog x y
                     in (f, tx)