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 8842265
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 14, 20262026-06-14T10:54:53+00:00 2026-06-14T10:54:53+00:00

I’m trying to write an enumerator for reading files line by line from a

  • 0

I’m trying to write an enumerator for reading files line by line from a java.io.BufferedReader using Scalaz 7’s iteratee library, which currently only provides an (extremely slow) enumerator for java.io.Reader.

The problems I’m running into are related to the fact that all of the other iteratee libraries I’ve used (e.g. Play 2.0’s and John Millikin’s enumerator for Haskell) have had an error state as one of their Step type’s constructors, and Scalaz 7 doesn’t.

My current implementation

Here’s what I currently have. First for some imports and IO wrappers:

import java.io.{ BufferedReader, File, FileReader }
import scalaz._, Scalaz._, effect.IO, iteratee.{ Iteratee => I, _ }

def openFile(f: File) = IO(new BufferedReader(new FileReader(f)))
def readLine(r: BufferedReader) = IO(Option(r.readLine))
def closeReader(r: BufferedReader) = IO(r.close())

And an type alias to clean things up a bit:

type ErrorOr[A] = Either[Throwable, A]

And now a tryIO helper, modeled (loosely, and probably wrongly) on the one in enumerator:

def tryIO[A, B](action: IO[B]) = I.iterateeT[A, IO, ErrorOr[B]](
  action.catchLeft.map(
    r => I.sdone(r, r.fold(_ => I.eofInput, _ => I.emptyInput))
  )
)

An enumerator for the BufferedReader itself:

def enumBuffered(r: => BufferedReader) = new EnumeratorT[ErrorOr[String], IO] {
  lazy val reader = r
  def apply[A] = (s: StepT[ErrorOr[String], IO, A]) => s.mapCont(k =>
    tryIO(readLine(reader)) flatMap {
      case Right(None)       => s.pointI
      case Right(Some(line)) => k(I.elInput(Right(line))) >>== apply[A]
      case Left(e)           => k(I.elInput(Left(e)))
    }
  )
}

And finally an enumerator that’s responsible for opening and closing the reader:

def enumFile(f: File) = new EnumeratorT[ErrorOr[String], IO] {
  def apply[A] = (s: StepT[ErrorOr[String], IO, A]) => s.mapCont(k =>
    tryIO(openFile(f)) flatMap {
      case Right(reader) => I.iterateeT(
        enumBuffered(reader).apply(s).value.ensuring(closeReader(reader))
      )
      case Left(e) => k(I.elInput(Left(e)))
    }
  )
}

Now suppose for example that I want to collect all the lines in a file that contain at least twenty-five '0' characters into a list. I can write:

val action: IO[ErrorOr[List[String]]] = (
  I.consume[ErrorOr[String], IO, List] %=
  I.filter(_.fold(_ => true, _.count(_ == '0') >= 25)) &=
  enumFile(new File("big.txt"))
).run.map(_.sequence)

In many ways this seems to work beautifully: I can kick the action off with unsafePerformIO and it will chunk through tens of millions of lines and gigabytes of data in a couple of minutes, in constant memory and without blowing the stack, and then close the reader when it’s done. If I give it the name of a file that doesn’t exist, it will dutifully give me back the exception wrapped in a Left, and enumBuffered at least seems to behave appropriately if it hits an exception while reading.

Potential problems

I have some concerns about my implementation, though—particularly of tryIO. For example, suppose I try to compose a few iteratees:

val it = for {
  _ <- tryIO[Unit, Unit](IO(println("a")))
  _ <- tryIO[Unit, Unit](IO(throw new Exception("!")))
  r <- tryIO[Unit, Unit](IO(println("b")))
} yield r

If I run this, I get the following:

scala> it.run.unsafePerformIO()
a
b
res11: ErrorOr[Unit] = Right(())

If I try the same thing with enumerator in GHCi, the result is more like what I’d expect:

...> run $ tryIO (putStrLn "a") >> tryIO (error "!") >> tryIO (putStrLn "b")
a
Left !

I just don’t see a way to get this behavior without an error state in the iteratee library itself.

My questions

I don’t claim to be any kind of expert on iteratees, but I have used the various Haskell implementations in a few projects, feel like I more or less understand the fundamental concepts, and had coffee with Oleg once. I’m at a loss here, though. Is this a reasonable way to handle exceptions in the absence of an error state? Is there a way to implement tryIO that would behave more like the enumerator version? Is there some kind of time bomb waiting for me in the fact that my implementation behaves differently?

  • 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-06-14T10:54:54+00:00Added an answer on June 14, 2026 at 10:54 am

    EDIT here is the real solution. I left in the original post because I think its worthwhile seeing the pattern. What works for Klesli works for IterateeT

    import java.io.{ BufferedReader, File, FileReader }
    import scalaz._, Scalaz._, effect._, iteratee.{ Iteratee => I, _ }
    
    object IterateeIOExample {
      type ErrorOr[+A] = EitherT[IO, Throwable, A]
    
      def openFile(f: File) = IO(new BufferedReader(new FileReader(f)))
      def readLine(r: BufferedReader) = IO(Option(r.readLine))
      def closeReader(r: BufferedReader) = IO(r.close())
    
      def tryIO[A, B](action: IO[B]) = I.iterateeT[A, ErrorOr, B] {
        EitherT.fromEither(action.catchLeft).map(r => I.sdone(r, I.emptyInput))
      }
    
      def enumBuffered(r: => BufferedReader) = new EnumeratorT[String, ErrorOr] {
        lazy val reader = r
        def apply[A] = (s: StepT[String, ErrorOr, A]) => s.mapCont(k =>
          tryIO(readLine(reader)) flatMap {
            case None => s.pointI
            case Some(line) => k(I.elInput(line)) >>== apply[A]
          })
      }
    
      def enumFile(f: File) = new EnumeratorT[String, ErrorOr] {
        def apply[A] = (s: StepT[String, ErrorOr, A]) => 
          tryIO(openFile(f)).flatMap(reader => I.iterateeT[String, ErrorOr, A](
            EitherT(
              enumBuffered(reader).apply(s).value.run.ensuring(closeReader(reader)))))
      }
    
      def main(args: Array[String]) {
        val action = (
          I.consume[String, ErrorOr, List] %=
          I.filter(a => a.count(_ == '0') >= 25) &=
          enumFile(new File(args(0)))).run.run
    
        println(action.unsafePerformIO().map(_.size))
      }
    }
    

    ===== Original Post =====

    I feel like you need an EitherT in the mix. Without EitherT you are just ending up with a 3 Lefts or Rights. With EitherT it would propergate the left.

    I think what you really want is

    type ErrorOr[+A] = EitherT[IO, Throwable, A] 
    I.iterateeT[A, ErrorOr, B]
    

    The following code mimics how you are currently composing things. Because IterateeT has no concept of left and right, when you compose it, you just end up with a bunch of IO/Id’s.

    scala> Kleisli((a:Int) => 4.right[String].point[Id])
    res11: scalaz.Kleisli[scalaz.Scalaz.Id,Int,scalaz.\/[String,Int]] = scalaz.KleisliFunctions$$anon$18@73e771ca
    
    scala> Kleisli((a:Int) => "aa".left[Int].point[Id])
    res12: scalaz.Kleisli[scalaz.Scalaz.Id,Int,scalaz.\/[String,Int]] = scalaz.KleisliFunctions$$anon$18@be41b41
    
    scala> for { a <- res11; b <- res12 } yield (a,b)
    res15: scalaz.Kleisli[scalaz.Scalaz.Id,Int,(scalaz.\/[String,Int], scalaz.\/[String,Int])] = scalaz.KleisliFunctions$$anon$18@42fd1445
    
    scala> res15.run(1)
    res16: (scalaz.\/[String,Int], scalaz.\/[String,Int]) = (\/-(4),-\/(aa))
    

    In the following code, instead of using Id, we use an EitherT. Since EitherT has the same bind behaviour as Either, we end up with what we want.

    scala>  type ErrorOr[+A] = EitherT[Id, String, A]
    defined type alias ErrorOr
    
    scala> Kleisli[ErrorOr, Int, Int]((a:Int) => EitherT(4.right[String].point[Id]))
    res22: scalaz.Kleisli[ErrorOr,Int,Int] = scalaz.KleisliFunctions$$anon$18@58b547a0
    
    scala> Kleisli[ErrorOr, Int, Int]((a:Int) => EitherT("aa".left[Int].point[Id]))
    res24: scalaz.Kleisli[ErrorOr,Int,Int] = scalaz.KleisliFunctions$$anon$18@342f2ceb
    
    scala> for { a <- res22; b <- res24 } yield 2
    res25: scalaz.Kleisli[ErrorOr,Int,Int] = scalaz.KleisliFunctions$$anon$18@204eab31
    
    scala> res25.run(2).run
    res26: scalaz.Scalaz.Id[scalaz.\/[String,Int]] = -\/(aa)
    

    You can replace Keisli with IterateeT and Id with IO to get what you need.

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

Sidebar

Related Questions

I have thousands of HTML files to process using Groovy/Java and I need to
I am trying to understand how to use SyndicationItem to display feed which is
I am reading a book about Javascript and jQuery and using one of the
I'm trying to select an H1 element which is the second-child in its group
I have a text area in my form which accepts all possible characters from
I'm trying to convert HTML to plain text. I get many &\#8217; &\#8220; etc.
I'm trying to decode HTML entries from here NYTimes.com and I cannot figure out
I have a bunch of posts stored in text files formatted in yaml/textile (from
Basically, what I'm trying to create is a page of div tags, each has
I'm new to using the Perl treebuilder module for HTML parsing and can't figure

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.