Skip to content

Instantly share code, notes, and snippets.

@YoEight
Last active December 31, 2015 22:09
Show Gist options
  • Select an option

  • Save YoEight/8051960 to your computer and use it in GitHub Desktop.

Select an option

Save YoEight/8051960 to your computer and use it in GitHub Desktop.
scalaz.Process and Free equiv. using simple structure encoding
sealed trait Free[F[_], A]
case class Return[F[_], A](v: A) extends Free[F, A]
case class Suspend[F[_], A](s: F[Free[F, A]]) extends Free[F, A]
sealed trait ProcessB[T[_], O, B]
case class Emit[T[_], O, B](o: O, next: B) extends ProcessB[T, O, B]
case class Await[T[_], A, O, B](ta: T[A], k: A => B) extends ProcessB[T, O, B]
case class Stop[T[_], O, B] extends ProcessB[T, O, B]
type Process[T[_], O] = Free[({ type F[x] = ProcessB[T,O,x] })#F, O]
@mandubian
Copy link

Let's go further and try to compare to iteratee seen as Free...
Can we design it like this?

sealed trait IterateeB[T[_], O, B]

case class Cont[T[_], I, O, B]( (=>I) => B ) extends IterateeB[T, O, B]
case class Done[T[_], O]( o: O ) extends IterateeB[T, O, B]
case class Error[T[_], O](msg: String) extends IterateeB[T, O, B]

type Iteratee[T[_], O] = Free[ ({ type F[x] = IterateeB[T, O, x] })#F, O]

@YoEight
Copy link
Author

YoEight commented Dec 20, 2013

About your first comment, as I said, it's a simple encoding. You can also lower type annotation using a covariance trick.

On the last comment, you get the idea. We can encode Iteratee like this.

@YoEight
Copy link
Author

YoEight commented Dec 20, 2013

Oups you're right about tail in Emit

@YoEight
Copy link
Author

YoEight commented Dec 20, 2013

Going further with ProcessB, Free is too powerful, using Mu is enough

case class Mu[F[_]](out: F[Mu[F]])

type Process[T[_], O] = Mu[({ type F[x] = ProcessB[T,O,x] })#F]

About IterateeB, you can drop Done (if you don't want leftovers, like you encoding it) because Return is equivalent

@mandubian
Copy link

You're completely right about dropping Done!
Emit is required for tail process but not iteratee!

Anyway, this makes me rethink about the Iteratee being just a function and the Process being interpreted...
Don't you think an iteratee as a Free becomes interpreted in some way?

The more I look at Process vs Iteratee, the more I believe one important difference is that Process awaits the result of T[_] whereas the Iteratee uses T[_] to generate next step...
It changes the way you manipulate both...
With Process, you need an initial T[A] to define a consuming machine with Await. So the T[_] controls the input.
In Process, the source is as important as the output. So you can design your stream from a producer to its consumer, from left to right...

With Iteratee, T[_] controls the output and we tend to define stream just from the consumer point of view (right to left)... Enumerator is quite artificial actually... I believe this makes Iteratee hard to manipulate for lots of people because it's harder to think just in terms of consumption... maybe one of the reasons why people don't feel at ease with iteratees

@YoEight
Copy link
Author

YoEight commented Dec 20, 2013

Anyway, this makes me rethink about the Iteratee being just a function and the Process being interpreted...
Don't you think an iteratee as a Free becomes interpreted in some way?

Yes, but I see no benefit.

The more I look at Process vs Iteratee, the more I believe one important difference is that Process awaits the result of T[_] whereas the Iteratee uses T[_] to generate next step

That's the key. Process abstracts the way you get an 'A', allowing a lot of reuse (ex: Process1, Tye, Wye). Process also lets its driver (i.e interpreter) decides how it want to deal the result. ex:

  • I want to execute that process sequentially
  • I want to execute that process in parallel
  • I want to do crazy stuff !

@mandubian
Copy link

Ok I agree with you!
But what can't you do with iteratee from these 3 points? (trying to find the bad arguments :))
you don't really control the source in iteratee, but you can control the output!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment