3

I am trying to parse a record from a lists of lists (continuing from this question).

Here's my record

data Record = Record Text Text Text Text Text Text Text Text Text deriving (Show, Generic)

This syntax works:

parseRecords :: [[Text]] -> [Record]
parseRecords = map (\[f1,f2,f3,f4,f5,f6,f7,f8,f9,_] -> Record f1 f2 f3 f4 f5 f6 f7 f8 f9)

This syntax checks, but has me fixed at 10 parameters. I would rather be able to have more than that and ignore the ones greater by pattern matching them into a [_] list I will not pass along. I tried the following:

parseRecords = map (\f1:f2:f3:f4:f5:f6:f7:f8:f9:[_] -> Record f1 f2 f3 f4 f5 f6 f7 f8 f9)

This, however, fails with:

Parse error (line 27, column 24): parse error on input ‘:’

I could have sworn I saw this kind of pattern matching used in lambdas before. What am I missing that my colon operators are a parse error? It is hard to interrogate what's going wrong.

Thanks!

6
  • 3
    You need an extra pair of parentheses around the pattern: (\(f1:f2:f3:f4:f5:f6:f7:f8:f9:[_]) -> Record f1 f2 f3 f4 f5 f6 f7 f8 f9) Commented Apr 13, 2019 at 21:27
  • 7
    The [_] is also wrong, you want just _. [_] is a pattern matching a list with exactly one element in it. Commented Apr 13, 2019 at 21:28
  • 1
    Are you sure you want a custom data type with 9 fields, all of the same type? This is going to get very cumbersome very quickly (it's pretty painful just seeing the brief code in your question). I don't know the use case, but I would strongly advise, at the very least, using record syntax if each piece of data has some simple characterisation. Commented Apr 13, 2019 at 21:34
  • @RobinZigmond no. My next step is to change this and use smart constructors, but need to crawl before I can run. Couldn't do much at all before I could pattern match and have it compile. Commented Apr 13, 2019 at 21:36
  • 1
    I appreciate the help everybody, but it really isn't easy to learn this stuff. Answers are often varying degrees of venomous RTFM and "closed-duplicate." I've read the books, but need practice, and asking for help on the internet takes some thick skin. As you can see, the compiler wasn't super helpful here, but I appreciate you all helped me find the error. It saved me maybe half a day of not understanding the bug and not having much to go on. Commented Apr 13, 2019 at 21:41

1 Answer 1

3

Just like you need parentheses around patterns in function bindings,

f (x:xs) = ...

you need parentheses around patterns in lambdas:

parseRecords = map (\ (f1:f2:f3:f4:f5:f6:f7:f8:f9:_) -> Record f1 f2 f3 f4 f5 f6 f7 f8 f9)
                      -------pattern----------------
                   ------------------lambda function--------------------------------------

Sometimes parentheses can be omitted, but not always. The list patterns are:

[]           matches     []
(x:xs)       matches     [x, ...]      so that   (x:xs)   == [x]   ++ xs
(x:y:xs)     matches     [x, y, ...]   so that   (x:y:xs) == [x]   ++ (y:xs)
                                                          == [x,y] ++ xs
..... and so on ......

This is because : associates to the right, so (x:y:xs) is actually (x:(y:xs)).

Lastly, _ is a wildcard. It is like a variable pattern like x or y or xs, but without a name. Each _ is different from another, as if it was named with a unique, though missing, name.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.