Scalaz iteratee, create Enumerator for BufferedReader - scala

How is it possible to create Enumerator for BufferedReader?
I found rather old article: http://apocalisp.wordpress.com/2010/10/17/scalaz-tutorial-enumeration-based-io-with-iteratees/ and it looks like it doesn't work with Scalaz 6.0.4
I try to create Enumerator based on example from here: Idiomatic construction to check whether a collection is ordered
implicit val ListEnumerator = new Enumerator[List] {
def apply[E, A](e: List[E], i: IterV[E, A]): IterV[E, A] = e match {
case List() => i
case x :: xs => i.fold(done = (_, _) => i,
cont = k => apply(xs, k(El(x))))
}
}
But I can't understand how to combine IO monad with Enumerator

What's wrong with RĂșnar's article? The following version is working for me (Scalaz 6.0.4):
object FileIteratee {
def enumReader[A](r: BufferedReader, it: IterV[String, A]) : IO[IterV[String, A]] = {
def loop: IterV[String, A] => IO[IterV[String, A]] = {
case i#Done(_, _) => i.pure[IO]
case i#Cont(k) => for {
s <- r.readLine.pure[IO]
a <- if (s == null) i.pure[IO] else loop(k(El(s)))
} yield a
}
loop(it)
}
def bufferFile(f: File) = new BufferedReader(new FileReader(f)).pure[IO]
def closeReader(r: Reader) = r.close().pure[IO]
def bracket[A,B,C](init: IO[A], fin: A => IO[B], body: A => IO[C]): IO[C] =
for {
a <- init
c <- body(a)
_ <- fin(a)
} yield c
def enumFile[A](f: File, i: IterV[String, A]) : IO[IterV[String, A]] =
bracket(bufferFile(f),
closeReader(_: BufferedReader),
enumReader(_: BufferedReader, i))
}

Related

Stateful computations in Scala using monads

I've been trying to learn functional programming in Scala, and I finally managed to understand how to use the for comprehension to work with state:
#!/usr/bin/env scala
case class State[A,S](run: S => (A,S)) {
def map[B](f: A => B): State[B,S] =
State(s => {
val (a, s1) = run(s)
(f(a), s1)
})
def flatMap[B](f: A => State[B,S]): State[B,S] =
State(s => {
val (a,s1) = run(s)
f(a).run(s1)
})
}
val increment = State[Unit,Int] {
x => ((),x+1)
}
val read = State[Int,Int] {
x => (x,x)
}
def prog = for {
_ <- increment
x <- read
_ <- increment
y <- read
} yield (x,y)
val ans = prog.run(0)._1
println(ans)
Although this runs fine, I did not manage to do something similar using a state monad, it is more complicated than, e.g., Option, because it takes an extra type. How do I do something similar to this code with a state monad?
EDIT: Apparently, my question was not clear. I want to run this using a monad trait, like this one, which I took from "Functional programming in Scala":
def stateMonad[S] = new Monad[({type lambda[x] = State[S,x]})#lambda] {
def unit[A](a: => A): State[S,A] = State(s => (a, s))
def flatMap[A,B](st: State[S,A])(f: A => State[S,B]): State[S,B] =
st flatMap f
}
And then perform the computation by instantiating this with something like val M = stateMonad[Int].
After trying around, I managed to get it working. So, I think I'll end up answering my own question. The solution is
trait Monad[M[_]] {
def unit[A](a: => A): M[A]
def flatMap[A,B](ma: M[A])(f: A => M[B]): M[B]
}
class StateMonad[S] extends Monad[({type lambda[x] = State[x,S]})#lambda] {
def unit[A](a: => A): State[A,S] = State(s => (a, s))
def flatMap[A,B](st: State[A,S])(f: A => State[B,S]): State[B,S] =
st flatMap f
def increment: State[Unit,Int] = State(x => ((),x+1))
def read: State[Int,Int] = State(x => (x,x))
}
val m = new StateMonad[Int]
def prog = for {
_ <- m.increment
x <- m.read
_ <- m.increment
y <- m.read
} yield (x,y)
The idea is to make the StateMonad class inherit from Monad, and include all the functions that manipulate state as methods of the StateMonad class. As was pointed out, my previous code could already be considered a monad, but I think doing it this way is better.

compiler error message when using State monad for memoization

I have a problem to make a working version of the Euler project problem 31 with the use of State trait (inspired from scalaz)
First, I have a solution with a mutable HashMap for memoization. It works but i would like to use the State monad, to understand it and to improve my skills.
I have used it with the fibonacci example, but when i attempt to apply the same technique to my case, i have a compiler error that i don't understand.
I use this implementation for State :
trait State[S, A] {
val run: S => (S, A)
def apply(s: S): (S, A) = run(s)
def eval(s: S): A = run(s)._2
def map[B](f: A => B): State[S, B] =
State { s: S =>
val (s1, a) = run(s)
(s1, f(a))
}
def flatMap[B](f: A => State[S, B]): State[S, B] =
State { s: S =>
val (s1, a) = run(s)
f(a)(s1)
}
}
object State {
def apply[S, A](f: S => (S, A)): State[S, A] = new State[S, A] {
final val run = f
}
def init[S, A](a: A) = State { s: S => (s, a) }
def update[S, A](f: S => S): State[S, Unit] = State { s: S => (f(s), ()) }
def gets[S, A](f: S => A): State[S, A] = State { s: S => (s, f(s)) }
}
my attempt to use it is here :
val coins = List(1, 2, 5, 10, 20, 50, 100, 200)
type MemoKey = (List[Int], Int)
type MemoType = Map[MemoKey, Int]
def ways(listCoins: List[Int], amount: Int): Int = {
def ways_impl(coins: List[Int], sum: Int): State[MemoType, Int] = (coins, sum) match {
case (Nil, 0) => State.init(1)
case (Nil, _) => State.init(0)
case (c :: cs, _) =>
for {
memoed <- State.gets { m: MemoType => m.get((coins, sum)) }
res <- memoed match {
case Some(way) => State.init[MemoType, Int](way)
case None =>
(for {
i <- 0 to sum / c
r <- ways_impl(cs, sum - i * c)
_ <- State.update { m: MemoType => m + ((coins, sum) -> r) }
} yield r).sum
}
} yield res
}
ways_impl(listCoins, amount) eval (Map())
I have a compiler error at this line :
r <- ways_impl(cs, sum - i * c)
The compiler said :
type mismatch; found : State[MemoType,Int] (which expands to) State[scala.collection.immutable.Map[(List[Int], Int),Int],Int] required: scala.collection.GenTraversableOnce[?]
For information, here is my first version with mutable map :
import scala.collection.mutable._
val memo = HashMap[(List[Int], Int), Int]()
val coins = List(1, 2, 5, 10, 20, 50, 100, 200)
def memoWays(coins: List[Int], sum: Int): Int = {
memo.getOrElse((coins, sum), {
val y = ways(coins, sum)
memo += ((coins, sum) -> y)
y
})
}
// brute force method with memoization
def ways(coins: List[Int], sum: Int): Int = (coins, sum) match {
case (Nil, 0) => 1
case (Nil, _) => 0
case (c :: cs, n) =>
(for {
i <- 0 to n / c
r = memoWays(cs, n - i * c)
} yield r).sum
}
println(s"result=${Mesure(ways(coins, 200))}")
What does that error mean ? Why the compiler want a GenTraversableOnce instead of State ?
What kind of thing i don't understand on State monad ?
And, if i may, I have an optional question :
Is my way to memoize with State Monad, is a good choice, or my first implementation with mutable map is better anyway ?
The problem is that your for comprehension is attempting to flatMap two unrelated types: a Range and a State. You're going to have to refactor, although off the top of my head, it's not clear to me how you'll be able to leverage State in a simple way. I'd probably use an immutable Map for the memo, a List to represent the future iterations to be tried, and simple recursion to iterate.

Use Cons operator for a custom trait

I have a MyStream-trait:
trait MyStream[+A] {
def uncons: Option[(A, MyStream[A])]
def isEmpty: Boolean = uncons.isEmpty
}
object MyStream {
def empty[A]: MyStream[A] =
new MyStream[A] { def uncons = None }
def cons[A](hd: => A, tl: => MyStream[A]): MyStream[A] =
new MyStream[A] { lazy val uncons = Some((hd, tl)) }
def apply[A](as: A*): MyStream[A] = if (as.isEmpty) empty
else cons(as.head, apply(as.tail: _*))
}
How can I use the uncons operator for pattern matching like:
def takeWhile(f: A => Boolean): MyStream[A] = this match {
case uncons(h,t) if f(h()) => cons(h(), t() takeWhile f)
case _ => empty
}
I am very new to Scala so I need a little help here.
Thanks!
How about this:
trait MyStream[+A] {
def uncons: Option[(A, MyStream[A])]
def isEmpty: Boolean = uncons.isEmpty
def takeWhile(f: A => Boolean): MyStream[A] = this match {
case MyStream(h, t) if f(h) => MyStream.cons(h, t takeWhile f)
case _ => MyStream.empty
}
#tailrec
final def foldLeft[B](z: B)(op: (B, A) => B): B =
this match {
case MyStream(h, t) => t.foldLeft(op(z, h))(op)
case _ => z
}
override def toString = this.foldLeft("") { case (acc, x) => acc + x }
}
object MyStream {
def empty[A]: MyStream[A] =
new MyStream[A] {
def uncons = None
}
def cons[A](hd: => A, tl: => MyStream[A]): MyStream[A] =
new MyStream[A] {
lazy val uncons = Some((hd, tl))
}
def apply[A](as: A*): MyStream[A] =
if (as.isEmpty) empty
else cons(as.head, apply(as.tail: _*))
def unapply[A](stream: MyStream[A]) = stream.uncons
}
object TestMyStream extends App {
import MyStream._
val s = cons(1, cons(2, cons(3, empty)))
println("All: " + s)
println("Take < 3: " + s.takeWhile(_ < 3))
}
prints:
All: 123
Take < 3: 12

Change list of Eithers to two value lists in scala

How can I change list of Eithers into two list of value Right and Left. When I use partition it returns two lists of Either's not values. What is the simplest way to do it?
foldLeft allows you to easily write your own method:
def separateEithers[T, U](list: List[Either[T, U]]) = {
val (ls, rs) = list.foldLeft(List[T](), List[U]()) {
case ((ls, rs), Left(x)) => (x :: ls, rs)
case ((ls, rs), Right(x)) => (ls, x :: rs)
}
(ls.reverse, rs.reverse)
}
You'll have to map the two resulting lists after partitioning.
val origin: List[Either[A, B]] = ???
val (lefts, rights) = origin.partition(_.isInstanceOf[Left[_]])
val leftValues = lefts.map(_.asInstanceOf[Left[A]].a)
val rightValues = rights.map(_.asInstanceOf[Right[B]].b)
If you are not happy with the casts and isInstanceOf's, you can also do it in two passes:
val leftValues = origin collect {
case Left(a) => a
}
val rightValues = origin collect {
case Right(b) => b
}
And if you are not happy with the two passes, you'll have to do it "by hand":
def myPartition[A, B](origin: List[Either[A, B]]): (List[A], List[B]) = {
val leftBuilder = List.newBuilder[A]
val rightBuilder = List.newBuilder[B]
origin foreach {
case Left(a) => leftBuilder += a
case Right(b) => rightBuilder += b
}
(leftBuilder.result(), rightBuilder.result())
}
Finally, if you don't like mutable state, you can do so:
def myPartition[A, B](origin: List[Either[A, B]]): (List[A], List[B]) = {
#tailrec
def loop(xs: List[Either[A, B]], accLeft: List[A],
accRight: List[B]): (List[A], List[B]) = {
xs match {
case Nil => (accLeft.reverse, accRight.reverse)
case Left(a) :: xr => loop(xr, a :: accLeft, accRight)
case Right(b) :: xr => loop(xr, accLeft, b :: accRight)
}
}
loop(origin, Nil, Nil)
}
If making two passes through the list is okay for you, you can use collect:
type E = Either[String, Int]
val xs: List[E] = List(Left("foo"), Right(1), Left("bar"), Right(2))
val rights = xs.collect { case Right(x) => x}
// rights: List[Int] = List(1, 2)
val lefts = xs.collect { case Left(x) => x}
// lefts: List[String] = List(foo, bar)
Using for comprehensions, like this,
for ( Left(v) <- xs ) yield v
and
for ( Right(v) <- xs ) yield v

How to convert a Twitter Future[Map[A, Future[C]]] to a Future[Map[A, C]]

I am trying to fix the following issue:
I have a Future[Map[A, B]]. For all B, I need to apply a method that convert B to a Future[C] and I want to give back a Future[Map[A, C]]
Here is the code I have so far:
def getClients(clientIds: Seq[Int]): Future[Map[Int, ClientData]] = {
def getClientData(clientInfo: ClientInfo): Future[ClientData] =
clientInfo match {
case ValidInfo(info) => getData(info)
case _ => throw new Exception
}
client.getClients(clientIds) map {
_.toMap map {
case (clientId: Int, clientInfo: ClientInfo) =>
getClientData(clientInfo) map {
clientData => (clientId, clientData)
}
}
}
}
This code is wrong as it returns a Iterable[Future[(Int, ClientData)]]
For info getClients is a thrift method that returns Future[Map[A, B]] where the Map is mutable, so I need to convert it to an immutable map first with toMap.
Thank you in advance for your help!
scala> def f: Future[Map[String, Future[Int]]] = ???
f: Future[Map[String,Future[Int]]]
scala> def x = for {
| m <- f
| i = m.map{ case (k, fv) => fv.map{ k -> _ } }
| l <- Future.sequence(i)
| } yield l.toMap
x: Future[Map[String,Int]]
Step by step:
Convert Future[Map[A, Future[B]]] to Future[Iterable[Future[(A, B)]]]:
scala> def x1 = f.map{ _.map{ case (k, fv) => fv.map{ k -> _ } } }
x1: Future[Iterable[Future[(String, Int)]]]
Convert Iterable[Future[(A, B)]] to Future[Iterable[(A, B)]] and flatten Future[Future[...]] using flatMap:
scala> def x2 = x1.flatMap{ Future.sequence(_) }
x2: Future[immutable.Iterable[(String, Int)]]
Convert Iterable[(A, B)] to Map[A, B]:
scala> def x = x2.map{ _.toMap }
x: Future[Map[String,Int]]
For com.twitter.util.Future you should use collect instead of sequence and toSeq before collect since it accepts Seq:
def x = for {
m <- f
i = m.map{ case (k, fv) => fv.map{ k -> _ } }
l <- Future.collect(i.toSeq)
} yield l.toMap