Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how could i return multiple values from a function in haskell?

Is it possible for a function to return multiple values – e.g., a string and a Boolean?

If yes, then I have a function called concat which returns a Bool and a String, but I don't know how to call that function so I can store the result.

Example attempt:

concat::(String->Int)->(IO Bool->IO String)
concat line i=do
       return True line

Can you help me to write the function signature and how to call those functions?

like image 813
rahul Avatar asked Jul 30 '14 17:07

rahul


People also ask

How can I return multiple values from a function?

If we want the function to return multiple values of same data types, we could return the pointer to array of that data types. We can also make the function return multiple values by using the arguments of the function.

How many values a function can return?

To that end, a function can only return one object.

Can go return multiple values?

In Go language, you are allowed to return multiple values from a function, using the return statement. Or in other words, in function, a single return statement can return multiple values. The type of the return values is similar to the type of the parameter defined in the parameter list.

How does return work in Haskell?

return is actually just a simple function in Haskell. It does not return something. It wraps a value into a monad. Looks like return is an overloaded function.


2 Answers

When returning multiple values you have to return an algebraic data type. Much can be said about this, I will give you some suggestions.

  1. If your Bool and String are somehow more related and they will be often together in your code, define a new algebraic data type:

    data Question = Question Bool String
    

    You can define it also with accessor functions, which document the data as well:

    data Question = Question{ answered :: Bool
                            , text     :: String }
    

    and you can define a function e. g. for initializing question:

    question :: String -> Question
    question str = Question False (str ++ "?")
    

    or (for improved documentation):

    question :: String -> Question
    question str = Question{ answered = False
                           , text     = str ++ "?"}
    

    then you can work with your data using data constructor:

    answer :: String -> Question -> Question
    answer answ (Question False str) =
      Question True (str ++ " " ++ answ ++ ".")
    answer _ old = old
    

    or using the accessor functions (many combinations of the two approaches are possible):

    answer :: String -> Question -> Question
    answer answ qstn
      | answered qstn = qstn
      | otherwise     = qstn{ answered = True
                            , text     = text qstn ++ " " ++ answ ++ "."}
    

    example of calling the functions:

    answer "Yes it is" (question "Is this answer already too long")
    
  2. If you don't want to define a new data type use a predefined one - tuple. There are many functions defined in standard libraries, which make your work with tuples easier. However, don't use the tuples everywhere - bigger code would become a mess (lack of documentation - it's not clear what data the tuple represents), type errors would not be so easy to trace due to polymorphism.

    An example of a kind-of-convenient use of tuples:

    squareAndCube :: Int -> (Int, Int)
    squareAndCube x = (square, square*x)
      where square = x*x
    
    sumOfSquareAndCube :: Int -> Int
    sumOfSquareAndCube x = square + cube
      where (square, cube) = squareAndCube x
    

    Too much said about this simple question but since I mentioned the standard library support as the main advantage of tuples, I'll give the last example which uses uncurry function from Prelude:

    sumOfSquareAndCube :: Int -> Int
    sumOfSquareAndCube x = uncurry (+) (squareAndCube x)
    
like image 178
pallly Avatar answered Oct 27 '22 12:10

pallly


Yes, you can return multiple values with a haskell construct called a tuple.

Here's a simple example

addAndSub :: Int -> Int -> (Int, Int)
addAndSub a b = (a + b, a - b)

You can then access the first part of the tuple with fst and the second with snd. However it's preferable to pattern match

use = case addAndSub 2 3 of
  (i, j) -> i + j

or

let (i,j) = addAndSub 2 3 
in i + j

Now let's say your function does some IO and gets a String and an Bool, your function would then look vaguely like

magic :: IO (String, Bool)
magic = do
  string <- getString
  bool   <- getBool
  return (string, bool)

If you're working in a monad with and using a do block, you can also pattern match using a prettier form.

foo = do
 (i, j) <- magic

Notice that this has to be in a do block. You can only use a do block if you're returning a value with the type m a where m is a monad, like IO.

like image 10
Daniel Gratzer Avatar answered Oct 27 '22 13:10

Daniel Gratzer