I am learning Haskell.
I am trying to find elements of a list as
which sum to elements of a list bs
, returning the elements as a tuple:
findSum2 :: [Int] -> [Int] -> [(Int,Int,Int)]
findSum2 as bs = [(a, a', b) | a <- as, a' <- as, b <- bs, a + a' == b]
The code works. But in order to learn Haskell, I'm trying to rewrite it as do-notation:
findSum2 :: [Int] -> [Int] -> [(Int,Int,Int)]
findSum2 as bs = do
a <- as
a' <- as
b <- bs
if a + a' == b then return (a, a', b) else return ()
The typechecker then complains at me:
• Couldn't match type ‘()’ with ‘(Int, Int, Int)’
Expected type: [(Int, Int, Int)]
Actual type: [()]
In all fairness, I knew it would. But since I can't skip the else
clause in Haskell, what should I put in the return statement in the else
clause?
Thanks.
You can not return the unit ( ()
), since that means that the return (a, a', b)
and the return ()
have different types: the first one is [(Int, Int, Int)]
, whereas the latter is [()]
.
What you can do is use an empty list in case the guard fails, so:
findSum2 :: [Int] -> [Int] -> [(Int,Int,Int)]
findSum2 as bs = do
a <- as
a' <- as
b <- bs
if a + a' == b then return (a, a', b) else []
You must return something of the correct type in the else
clause. It could be the empty list []
, or one of the abstracted values like mzero
or empty
.
Or you could remove the if
expression and use the guard
function.
import Control.Monad (guard)
findSum2 :: [Int] -> [Int] -> [(Int,Int,Int)]
findSum2 as bs = do
a <- as
a' <- as
b <- bs
guard (a + a' == b)
return (a, a', b)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.