Search code examples
listhaskellrecursionreturn

Haskell Recursion how to return an empty list and ignore recursively generated list


I'm writing a recursive function that builds a list, but has some conditions where, if met, the function should ignore the list that's been built so far and simply return an empty list on its own.

A simple example:

func (x:xs)
   | x < 10 = [x] ++ func xs
   | otherwise = ("return an empty list without the already built up list")

So if xs was a list [1 .. 12] then once it's built a list that's [1..9] then when it reaches 10, it'll disregard the list it's built and just return an empty array [], and not return an empty array that's passed back to the already built up list.

Is there a way to do this in Haskell? I've tried doing return [] but it gave me the error:

Couldn't match expected type ‘Int’ with actual type ‘[t0]’


Solution

  • return is not a statement in Haskell, but even if it was it would not work anyway. Since due to recursion, you then return that list at that specific level.

    It looks however that you simply want to know if all elements are smaller than 10. If that is the case, you return the entire list, otherwise you return an empty list.

    You can do that with:

    func :: (Num a, Ord a) => [a] -> [a]
    func xs | all (< 10) xs = xs
            | otherwise = []
    

    or we can use recursion, and make use of Maybe:

    func :: (Num a, Ord a) => [a] -> Maybe [a]
    func [] = Just []
    func (x:xs) | x < 10 = fmap (x:) (func xs)
                | otherwise = Nothing
    

    We can then later convert the Nothing value with fromMaybe :: a -> Maybe a -> a to an empty list, although a Maybe might be better idea here, that allows us to differentatie between func [] and func [14] for example.