Search code examples
haskellpattern-matchingparse-error

Haskell: Parse error in pattern x ++ xs


Doing the third of the 99-Haskell problems (I am currently trying to learn the language) I tried to incorporate pattern matching as well as recursion into my function which now looks like this:

myElementAt :: [a] -> Int -> a
myElementAt (x ++ xs) i =
  if length (x ++ xs) == i && length xs == 1 then xs!!0
  else myElementAt x i

Which gives me Parse error in pattern: x ++ xs. The questions:

  1. Why does this give me a parse error? Is it because Haskell is no idea where to cut my list (Which is my best guess)?
  2. How could I reframe my function so that it works? The algorithmic idea is to check wether the list has the length as the specified inde; if yes return the last elemen; if not cut away one element at the end of the list and then do the recursion.

Note: I know that this is a really bad algorithm, but it I've set myself the challenge to write that function including recursion and pattern matching. I also tried not to use the !! operator, but that is fine for me since the only thing it really does (or should do if it compiled) is to convert a one-element list into that element.


Solution

  • Haskell has two different kinds of value-level entities: variables (this also includes functions, infix operators like ++ etc.) and constructors. Both can be used in expressions, but only constructors can also be used in patterns.

    In either case, it's easy to tell whether you're dealing with a variable or constructor: a constructor always starts with an uppercase letter (e.g. Nothing, True or StateT) or, if it's an infix, with a colon (:, :+). Everything else is a variable. Fundamentally, the difference is that a constructor is always a unique, immediately matcheable value from a predefined collection (namely, the alternatives of a data definition), whereas a variable can just have any value, and often it's in principle not possible to uniquely distinguish different variables, in particular if they have a function type.

    Yours is actually a good example for this: for the pattern match x ++ xs to make sense, there would have to be one unique way in which the input list could be written in the form x ++ xs. Well, but for, say [0,1,2,3], there are multiple different ways in which this can be done:

    [] ++[0,1,2,3]
    [0] ++ [1,2,3]
    [0,1] ++ [2,3]
    [0,1,2] ++ [3]
    [0,1,2,3]++ []
    

    Which one should the runtime choose?