-
-
Save YoEight/8051960 to your computer and use it in GitHub Desktop.
| 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] |
Oups you're right about tail in Emit
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
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
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 !
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!
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.