2

I've been looking to write a lexer in Haskell and stumbled upon these functions.

If defined, some and many should be the least solutions of the equations:

some v = (:) <$> v <*> many v

many v = some v <|> pure []

I get that the (:) in some gets lifted and applied to the value of v in order to prepend it to the list returned in many v.

But why does the definition of many start with some? And why does it get concatenated with pure []?

What is the relationship or difference between these two functions? What does it mean for some and many to be the least solutions of those equations? And how does the recursion ever stop? Help!

Will Ness
  • 70,110
  • 9
  • 98
  • 181
northlane
  • 293
  • 1
  • 9
  • 8
    It doesn't get *concatenated* with `pure []`. The empty list is the *alternative* where the recursion stops. – Bergi Aug 14 '17 at 00:38
  • 8
    `some` means "at least one" while `many` means "none or more". – Bergi Aug 14 '17 at 00:39
  • Aha thank you. I think this is starting to make sense. So the some guarantees at least one value, followed by 0 or more, and many gives you at least one value (plus 0 or more) *or* nothing. But how exactly does the recursion end? How do values from v get consumed? – northlane Aug 14 '17 at 01:20
  • 3
    Values from `v` do not get consumed. `some` and `many` are producing a (in a sense) 'larger' value than their input. Recursion ends only if `<*>` and `<|>` are sufficiently lazy. This isn't the case for `[]` or `Maybe`, but it is the case for `IO`. e.g., `many (getLine >>= \x -> if all isDigit x then return x else empty)` will read lines until you enter something containing a non-digit. – user2407038 Aug 14 '17 at 02:01

1 Answers1

5
  • some p means one or more match of p
  • many p means zero or more more match of p

For input "abc", many letter and some letter will both parse abc.

But for input "123", many letter will output empty string "". some letter will report error.

According to the definition. some v needs at least 1 match of v, so we can first parse v then we need 0 or more match of v, which is many v. It is something like :

some v = do
    first_match <- v
    rest_matches <- many v
    return $ first_match : rest_matches

which is the same as some v = (:) <$> v <*> many v.

But for many v. It will either match some v (1 or more) or nothing (pure []).

many v = if matches (some v) then return (some v) else return nothing.

You can try solve writing applicative parsers from scratch from codewars.

Functional pearls is also a very good reference about parse combinators.


  1. https://www.codewars.com/kata/writing-applicative-parsers-from-scratch
  2. http://www.cs.nott.ac.uk/~pszgmh/pearl.pdf
delta
  • 3,778
  • 15
  • 22