Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I pattern match on the concatenation function (++) in Haskell?

I'm trying to match **String Newline String** pattern in a function Split.

split::String -> [String]
split[] = []
split (x++'\n':xs) = [x]++split(xs)

I'm getting this error: Parse error in pattern: x ++ ('\n' : xs)

What am I doing wrong here?

I know there are other ways of achieving the same result but I'd like to understand what wrong with this pattern. I'm fairly new to Haskell BTW.

like image 984
farhanhubble Avatar asked Dec 11 '15 06:12

farhanhubble


People also ask

Does Haskell have pattern matching?

We use pattern matching in Haskell to simplify our codes by identifying specific types of expression. We can also use if-else as an alternative to pattern matching. Pattern matching can also be seen as a kind of dynamic polymorphism where, based on the parameter list, different methods can be executed.

How does pattern matching work in Haskell?

Pattern matching consists of specifying patterns to which some data should conform and then checking to see if it does and deconstructing the data according to those patterns. When defining functions, you can define separate function bodies for different patterns.

Why ++ is not allowed in pattern matching?

You can only pattern-match on data constructors, and ++ is a function, not a data constructor. Data constructors are persistent; a value like 'c':[] cannot be simplified further, because it is a fundamental value of type [Char] .


1 Answers

One problem (as I understand it) is that ++ is not a constructor of the list data type the way : is. You can think of the list data type being defined as

data [a] = [] | a : [a]

Where : is a constructor that appends elements to the front of a list. However, ++ is a function (defined in the documentation here: http://hackage.haskell.org/package/base-4.8.1.0/docs/src/GHC.Base.html#%2B%2B) as

(++) :: [a] -> [a] -> [a]
(++) []     ys = ys
(++) (x:xs) ys = x : xs ++ ys

We could define our own data type list like

data List a = Empty | Cons a (List a)

That would mimic the behavior of our familiar list. In fact, you could use (Cons val) in a pattern. I believe you could also define a type with a concat constructor like so

data CList a = Empty | Cons a (CList a) | Concat (CList a) (CList a)

Which you could use to lazily concatenate two lists and defer joining them into one. With such a data type you could pattern match against the Concat xs ys input, but you that would only work on the boundary of two lists and not in the middle of one.

Anyway I'm still fairly new to Haskell myself but I hope this is on point.

like image 86
beigel Avatar answered Oct 25 '22 06:10

beigel