I was just listening to https://www.youtube.com/watch?v=o3Siln85TJ4 and heard Runar mention that Process1 should be named Pipe (around minute 25) . I agree that that would be a better name (and saw that it's still called Process1).
Any opinions about renaming this?
The 0.9 version of Process1 is much different than 0.8 and prior. Consider these aliases from 0.9:
type Process1[-I,+O] = Stream[Pure,I] => Stream[Pure,O]
type Channel[F[_],-I,+O] = Stream[F,I] => Stream[F,O]
type Sink[F[_],-I] = Channel[F,I,Unit]
type Tee[-I,-I2,+O] = (Stream[Pure,I], Stream[Pure,I2]) => Stream[Pure,O]
type Wye[F[_],-I,-I2,+O] = (Stream[F,I], Stream[F,I2]) => Stream[F,O]
There are some interesting symmetries here. Process1[I,O] is really a Channel[Pure,I,O]. A Tee[I,I2,O] is really a Wye[Pure,I,I2,O].
Now consider these operations defined on a Stream[F,A]:
def pipe[B](f: Process1[A,B]): Stream[F,B] = ???
def pipev[F2[_],B](f: Channel[F2,A, B])(implicit S: Sub1[F,F2]): Stream[F2,B] = ???
def pipe2v[F2[_],B,C](s2: Stream[F2,B])(f: (Stream[F2,A], Stream[F2,B]) => Stream[F2,C])(implicit S: Sub1[F,F2]): Stream[F2,C] = ???
Regardless of whether you have a Process1, a Channel, a Wye, or a Tee, you can apply it to a stream via a variant of pipe.
I had a conversation with @pchiusano about the name Process1 during the 0.9 redesign work. His explanation was that Process1 is streamy analogue of Function1. Paul had mentioned perhaps coming up with a naming scheme that covered both dimensions -- arity and effectful/pure. Today we have:
| Type | Arity | Pure/Effectful |
| --- | --- | --- |
| Process1 | Arity 1 | Pure |
| Channel | Arity 1 | Effectful |
| Tee | Arity 2 | Pure |
| Wye | Arity 2 | Effectful |
If we rename Process1 and further break downstream projects in the 0.9 release, I'd like to see a naming convention that's predictable based on those axes.
@mpilquist thanks for the great write up, very useful!
I think Process1 is at the moment "baseless", right? (in the sense that there was a Process in 0.8, but this has vanished in the current version) So that makes me think all the more that it would be good to rename Process1.
Having predictable names on the arity and pure/effectful axes would be great. How about something along these lines?
type Pipe[F[_],-I,+O] = Stream[F,I] => Stream[F,O]
type PurePipe[-I,+O] = Stream[Pure,I] => Stream[Pure,O]
type Sink[F[_],-I] = Pipe[F,I,Unit]
type Tee[F[_],-I,-I2,+O] = (Stream[F,I], Stream[F,I2]) => Stream[F,O]
type PureTee[-I,-I2,+O] = (Stream[Pure,I], Stream[Pure,I2]) => Stream[Pure,O]
Line of thinking:
F[_]) have a short name (Pipe, Tee)PurePipe, PureTee)Pipe because that fits nicely with the methods on Stream: someStream.pipe(somePipe) (also it matches metaphorically/visually, at least in my head)Tee also fits the Pipe metaphor, but an alternative could be to name that Pipe2 instead, so that there's a consistent naming path to Pipe<n> I like the Process naming over Pipe mainly because it implies computation. You pipe a Stream to a process to transform it into a new Stream.
After talking about it more with a few folks, I think we should drop the aliases that fix F = Pure because they are a lie. The methods in the fs2.process1 object all return channels that are polymorphic in F, not Process1s. The methods in the fs2.tee object all return wyes that are polymorphic in F. These are a clues that the aliases shouldn't exist.
So here's what I'm thinking:
type Pipe[F[_],-I,+O] = Stream[F,I] => Stream[F,O]
type Pipe2[F[_],-I,-I2,+O] = (Stream[F,I], Stream[F,I2]) => Stream[F,O]
Then we rename fs2.process1 object to fs2.pipe and we merge the fs2.tee and fs2.wye objects in to a new fs2.pipe2 object. Finally, we rename the existing pipe methods to through (e.g., through, through2, throughv).
I spoke with @pchiusano and he's okay with the above.
I'll put a PR together tonight or tomorrow for folks to evaluate unless there are strong objections.
Generally +1. Though pipe1 through pipe1: Pipe1 and pipe1 throughLeft/right pipe2 :Pipe2 will be nice too. Of course naming is draft.
Sent from my iPhone
On 20. 4. 2016, at 19:36, Michael Pilquist [email protected] wrote:
After talking about it more with a few folks, I think we should drop the aliases that fix F = Pure because they are a lie. The methods in the fs2.process1 object all return channels that are polymorphic in F, not Process1s. The methods in the fs2.tee object all return wyes that are polymorphic in F. These are a clues that the aliases shouldn't exist.
So here's what I'm thinking:
type Pipe[F[_],-I,+O] = Stream[F,I] => Stream[F,O]
type Pipe2[F[_],-I,-I2,+O] = (Stream[F,I], Stream[F,I2]) => Stream[F,O]
Then we rename fs2.process1 object to fs2.pipe and we merge the fs2.tee and fs2.wye objects in to a new fs2.pipe2 object. Finally, we rename the existing pipe methods to through (e.g., through, through2, throughv).I spoke with @pchiusano and he's okay with the above.
I'll put a PR together tonight or tomorrow for folks to evaluate unless there are strong objections.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub
PR here: https://github.com/functional-streams-for-scala/fs2/pull/581
@pchlupacek I didn't add your suggestions yet. I figured we can do that after the initial merge. Some quick thoughts:
p1 through p2 is really just p1 andThen p2 so I don't think we need this one@mpilquist sure. I am just tackling the beauty of 0.8 where we had possibilities like
val wye2 = (p1 pipe p2) attachL wye
p.wye(p2)(wye2)
@pchlupacek OK, I got pipe operators working. I added covary, attachL, and attachR: https://github.com/functional-streams-for-scala/fs2/pull/581/commits/376e98bc092bd1236fd6d6ac274eb1d8b9cc8911
@mpilquist excellent thanks,
Fixed by #581
Most helpful comment
After talking about it more with a few folks, I think we should drop the aliases that fix
F=Purebecause they are a lie. The methods in thefs2.process1object all return channels that are polymorphic inF, notProcess1s. The methods in thefs2.teeobject all return wyes that are polymorphic inF. These are a clues that the aliases shouldn't exist.So here's what I'm thinking:
Then we rename
fs2.process1object tofs2.pipeand we merge thefs2.teeandfs2.wyeobjects in to a newfs2.pipe2object. Finally, we rename the existingpipemethods tothrough(e.g.,through,through2,throughv).I spoke with @pchiusano and he's okay with the above.
I'll put a PR together tonight or tomorrow for folks to evaluate unless there are strong objections.