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?
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.
To that end, a function can only return one object.
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.
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.
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
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")
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With