Search code examples
if-statementhaskellindentationparse-error

Haskell function that returns a list of elements in a list with more than given amount of occurrences


I tried making a function that as in the title takes 2 arguments, a number that specifies how many times the number must occur and a list that we are working on, I made a function that counts number of appearances of given number in a list and I tried using it in my main function, but I cannot comprehend how the if else and indentations work in Haskell, it's so much harder fixing errors than in other languages, i think that I'm missing else statement but even so I don't know that to put in there

count el list = count el list 0
     where count el list output
             | list==[] = output
             | head(list)==el = count el (tail(list)) output+1
             | otherwise = count el (tail(list)) output


moreThan :: Eq a => Int -> [a] -> [a]
moreThan a [] = []
moreThan a list = moreThan a list output i
    where moreThan a list [] 0
            if i == length (list)
                then output
            else if elem (list!!i) output
                 then moreThan a list output i+1
            else if (count (list!!i) list) >= a 
                then moreThan a list (output ++ [list!!i]) i+1 

All I get right now is

parse error (possibly incorrect indentation or mismatched brackets) 

Solution

  • You just forgot the = sign and some brackets, and the final else case. But also you switched the order of the internal function declaration and call:

        moreThan :: Eq a => Int -> [a] -> [a]
        moreThan a [] = []
        moreThan a list = go a list [] 0   -- call
            where go a list output i =      --  declaration  =
                    if i == length (list)
                        then output
                    else if elem (list!!i) output
                         then go a list output (i+1)    -- (i+1) !
                    else if (count (list!!i) list) >= a 
                        then go a list (output ++ [list!!i]) (i+1)   -- (i+1) !
                    else
                        undefined
    

    I did rename your internal function as go, as is the custom.

    As to how to go about fixing errors in general, just read the error messages, slowly, and carefully -- they usually say what went wrong and where.

    That takes care of the syntax issues that you asked about.

    As to what to put in the missing else clause, you've just dealt with this issue in the line above it -- you include the ith element in the output if its count in the list is greater than or equal to the given parameter, a. What to do else, we say in the else clause.

    And that is, most probably, to not include that element in the output:

                        then go a list (output ++ [list!!i]) (i+1)
                    else               ---------------------
                        undefined
    

    So, just keep the output as it is, there, instead of the outlined part, and put that line instead of the undefined.

    More importantly, accessing list elements via an index is an anti-pattern, it is much better to "slide along" by taking a tail at each recursive step, and always deal with the head element only, like you do in your count code (but preferably using the pattern matching, not those functions directly). That way our code becomes linear instead of quadratic as it is now.