Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6679951
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 26, 20262026-05-26T04:25:06+00:00 2026-05-26T04:25:06+00:00

I have a list of values from which I can construct a list of

  • 0

I have a list of values from which I can construct a list of parsers, that depend on these values by mapping (see example). Then what I want to do is turn the list of parsers into a single parser by concatenation.

One possibility is using foldLeft and ~:

parsers.foldLeft(success(Nil)){case (ps,p) => rs ~ p ^^ {case xs ~ x => x ::xs}} ^^ (_.reverse)

Is this efficient?

I don’t know how combinator parsers work; will there be a call stack with depth of length of the list? Thus may I run into SO errors for very long concatenations?

Better way

Is there a different way that is more readable?

Example

Suppose you have a file with two lines. The first line contains n integers x_1 to x_n. The second line contains contains x_1 + x_2 + … x_n integers that belong to groups according to the first line. I want to take the sequence of integers from the first line and create n parsers p_1 to p_n where p_i parses x_i integers.

Suppose I have the list of integers l = List(1,2,3) from the first line. For each integer n I create a parser that parses n integers: parsers = l.map(repN(_,integer)).

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-26T04:25:06+00:00Added an answer on May 26, 2026 at 4:25 am

    What you’re describing (and what you’ve more or less reinvented in your implementation with foldLeft and ~) is essentially Haskell’s sequence for monads (really you only need an applicative functor, but that’s irrelevant here). sequence takes a list of monadic values and returns a monadic list of values. Parser is a monad, so sequence for Parser would change a List[Parser[A]] into a Parser[List[A]].

    Scalaz gives you sequence, but off the top of my head I don’t know if there’s a nice way to get the necessary Applicative instance for Parser. Fortunately you can roll your own pretty easily (I’m directly translating the Haskell definition):

    import scala.util.parsing.combinator._
    
    object parser extends RegexParsers {
      val integer = """\d+""".r
    
      val counts = List(1, 2, 3)
      val parsers = counts.map(repN(_, integer))
    
      val line = parsers.foldRight(success(Nil: List[List[String]])) {
        (m, n) => for { x <- m ; xs <- n } yield (x :: xs)
      }
    
      def apply(s: String) = parseAll(line, s)
    }
    

    This gives us List(List(1), List(2, 3), List(4, 5, 6)) for parser("1 2 3 4 5 6"), as desired.

    (Note that I’m using RegexParsers here as a convenient complete example, but the approach works more generally.)

    What’s going on might be a little clearer if we desugar the for comprehension:

    val line = parsers.foldRight(success(Nil: List[List[String]])) {
      (current, acc) => current.flatMap(x => acc.map(x :: _))
    }
    

    We can write flatMap as into and map as ^^:

    val line = parsers.foldRight(success(Nil: List[List[String]])) {
      (current, acc) => current into (x => acc ^^ (x :: _))
    }
    

    This isn’t too far from your formulation, except that we’re using a right fold instead of reversing and aren’t building up and breaking down the ~s.


    About efficiency: Both of our implementations are going to result in unpleasant call stacks. In my experience this is just a fact of life with Scala’s parser combinators. To quote another Stack Overflow answer, for example:

    Scala’s parser combinators aren’t very efficient. They weren’t
    designed to be. They’re good for doing small tasks with relatively
    small inputs.

    My sequence-y approach addresses the “more readable” part of your question, and is almost certainly the cleanest way to solve the problem with Scala’s parser combinators. It’s marginally more efficient than your implementation, and should be fine for a few thousand groups or so. If you need to handle more than that, you’ll have to look outside of scala.util.parsing.combinator. I’d recommend something like the following:

    def parse(counts: Seq[Int], input: String): Option[Seq[Seq[Int]]] = {
      val parsed = try {
        Some(input.split(" ").map(_.toInt))
      } catch {
        case _ : java.lang.NumberFormatException => None
      }
    
      parsed.flatMap { ints =>
        if (ints.length != counts.sum) None
        else Some(counts.foldLeft((Seq.empty[Seq[Int]], ints)) {
          case ((collected, remaining), count) => {
            val (m, n) = remaining.splitAt(count)
            (m.toSeq +: collected, n)
          }
        }._1.reverse)
      }
    }
    

    No guarantees, but on my system it doesn’t overflow on a line with 100k integer groups.


    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have a select list which is being populated using the values from a
I have the following sample code which gets a list of values from a
I have a list of values such as 12000,12345,123456 that need to be converted
I have a list of values that I am looping through, determining whether each
I have a list of string values that I want add to a hashtable
Users of my application have the possibility of choosing some values from list. The
I have a list that contain two colums which are type currency. I want
I have a list of values like this 1000, 20400 22200, 24444 The ranges
I have a list of values as such: row = ['0x14', '0xb6', '0xa1', '0x0',
I have a list of numeric values. I may normalize the values if needed.

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.