how could i return multiple values from a function in haskell?
When returning multiple values you have to return an algebraic data type. Much can be said about this, I will give you some suggestions.
If your
Bool
andString
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")
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)
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
.