0

Currently I have faced the following code that I have no idea on how this data constructor works. The code snippet is as follow:

data Parser a b = P {
  runParser :: Stream a -> [(b, Stream a)]
}

I understand that Haskell can have something called recorded syntax, but for this one, that is a bit blow my mind up.

Thanks for the help.

4
  • 1
    What part specifically are you having problems understanding? There's a lot going on here, and an overview of it all would be too broad. Have you looked how records work? Commented Jun 4, 2018 at 15:52
  • @Carcigenicate Stream a -> [(b, Stream a)] is this means if I type :t runParser in ghci, I will got Parser a b -> Stream a -> [(b,Stream a)] ??? Commented Jun 4, 2018 at 15:55
  • Did you try that to see? And Stream a -> [(b, Stream a)] is a function that takes a Stream, and returns a list of tuples where the first element is of type b, and the second is a Stream of a's. Commented Jun 4, 2018 at 15:57
  • The record syntax does not change anything. In functional programming: functions are "first class citizens". You can pass them as arguments, return them as a result, and store them in a constructor. Commented Jun 4, 2018 at 16:11

1 Answer 1

4

Well basically this is just regular record synax:

data Parser a b = P {
  runParser :: Stream a -> [(b, Stream a)]
}

It means that the Parser a b data type has one data constructor. A data constructor named P, and that constructor has one argument: a "field" called runParser, and that field has type Stream a -> [(b, Stream a)].

This pattern is quite common in Haskell and in functional programming in general. Functions are "first class citizens". It means that functions can be passed as arguments, a function can return another function (in fact due to currying this happens very often in Haskell), and we can store (references to) function in a data constructor.

We can for example create a Parser Int Char type with:

P (\_ -> []) :: Parser Int Char

So here we constructed a Parser Int Char and the argument, a single function, maps any value to an empty list.

Or another example:

P (\x -> [('a', x), ('b', x)]) :: Parser Int Char

Here we thus map our Stream a object x, to a list of 2-tuples, one with 'a' as first element, and one with 'b' as first element. Each time we pick x as second element.

Or we can define a function, and pass a reference to that function:

f :: Stream Int -> [(Char, Stream Int)]
f x = [('a', x)]

P f :: Parser Int Char
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, I will take a look on that :)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.