-
Notifications
You must be signed in to change notification settings - Fork 196
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC: Stop using the type synonyms in library type signatures #283
Comments
Assuming the change happens I'd like to see commentary in the code for folks learning the library like: -- type signature equivalent func :: a -> b -> Source o m I found the type synonyms confusing when I first got to reading the code. But I find the synonyms provide a helpful shorthand in my own code now that I understand what's going on. |
After reading through the new tutorial my impression is that the type synonyms to not help at all. They might lead me to think that a |
Would it be feasible to drop the M from ConduitM, also ? |
I've thought about that, but that would be some major breakage. It's On Fri, Oct 14, 2016, 5:53 PM Simon Michael notifications@github.com
|
Is The whole Void vs () is the nasty piece. I thought at one point the type synonyms helped to paper that over, but it doesn't seem to anymore, so their value is much less. I'm sure this has already occurred to you, and been rejected for being silly in some way, but is rank2 polymorphism enough?
Might that encode that you don't look at the values of the input or output? (I assume this idea is silly, I certainly haven't sanity checked it, but it occurs to me so seems worth writing at least.) |
This is the first I'm hearing of the The rank2 polymorphism approach is something I'd like to avoid, this library has already suffered a lot from impredicative types popping up everywhere. |
Ripping bandaids is always painful in the short term - not sure if it's a good idea or not. It's the void/() asymmetry that is the problem. Some places are positive, some are negative, so I appreciate the duality. But juggling co/contra-variant in my head always makes me want a drink, so I imagine beginners don't find it any easier. Point taken on impredicativity - it sounds like you're saying "plausible idea, but the tools will beat you to death for it". That makes sense. How about:
I'm going to feed you inputs, and ignore your outputs entirely. The fact you've statically proved there are no outputs doesn't really matter. I think of it as somewhat equivalent to should Also note that if you could avoid |
If you're going to go that far, we can actually just go for: runConduit :: Monad m => ConduitM i o m r -> m r We can promise to deliver a stream of any value, and then simply never produce them. The only question is: does this make errors from users more or less likely? I've gone under the assumption so far of enforcing the invariants is a good thing, but I'm open to the idea of just relaxing it. That could even be done with a minor version bump AFAICT. The ripping bandaids part could be done in parts, such as by marking the type synonyms as deprecated now, and then having a conduit 1.3 release in a few months that s/ConduitM/Conduit. Another possible name to throw into the mix that doesn't break anything is Possibilities to consider in all of this are also deprecating the other operators. All options are on the table here. |
I was expecting For operator depreciation, I tend to prefer stages - first make them direct synonyms at the source and say "use this instead". Then wait and deprecate them. Then remove them. No rush, but they should be clearly signposted as "not for future use". |
No. The conduit await >>= maybe loop return But I'm not too terribly worried about that. It's really about preventing someone from doing something like: runConduit $ sourceFile "foo"
-- or
runConduit $ sinkFile "foo" The way I agree on slow and steady on the operators. |
I note the first of those will almost certainly raise an error when they try and use the result from
I appreciate the guarantees Void provides, but I'm skeptical they are worth the cost given the beginner-unfriendlyness of Void. |
Is Void really that bad? Seems simple to me. Or is it just the positive/negative alteration that's hard? |
Void is not trivial. Positive/negative is genuinely hard. I observe that the current tutorial says:
Or "magic lies here". Better to remove the magic than upset the muggles. |
By that argument we wouldn't have a Monad type class. :) I like Void, and know very little about conduit, but have been messing around with Haskell for a long time. What is the reasoning for using () in the input? I mean () is a content-less signal, and Void is /actually no information/, and I think that distinction, while made blurry by the way the compiler handles case statements is still useful. |
Ah no, different concepts carry different amounts of water and have different degrees of difficulty associated with them. Conflation doesn't make your point stronger. IME, the problems with Conduit for myself and for beginners were type tetris / thrashing, not |
Yes, monads are a lot harder than Void. Though more clearly worth it because they are also useful for a lot more things. Though haskell being lazy and having bottum makes the distinction between Void and () somewhat unreal. |
In the context of conduit is there any benefit (beyond a
|
It's just a stronger statement of "this thing doesn't yield anything." There's certainly an argument to be made that discarding a stream of All of this together is certainly pushing me towards a conduit-1.3 (or 2.0?) breaking change release. I'll probably start working properly on a branch soon, and would love feedback when I get deeper into it. |
I agree that a 2.0 release would be wise given the number of breaking
|
@snoyberg One question is whether we believe beginners would think of the use-case of a source of Again, I haven't seen |
I started using conduit at the beginning of this year. The type synonyms didn't confuse me until I started reading about them. From README.md:
Makes sense. I can still
This doesn't make sense to me. I can still consume values with It seems to me that the typedef should be: type Source m o = ConduitM Void o m () Then, if I
This makes sense. If I wanted to produce an output, I would need something of type
I don't understand how it's possible to produce in this case. I would need something of type |
I've created a PR for just the deprecation aspect of things here: #307. |
Reasons:
Source
andProducer
(orSink
andConsumer
) is subtle and trickyDownsides:
Please use 👍 and 👎 reactions on this description to express support/opposition to this change.
The text was updated successfully, but these errors were encountered: