-
Notifications
You must be signed in to change notification settings - Fork 59
Add =% for monadic operations #1150
Conversation
belisarius222
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM this is very cool
|
Making one last bid to use a ; rune for this, and leave =% open for
integration of something like /: into the hoon grammar :P
…On 4/16/19, Ted Blackman ***@***.***> wrote:
belisarius222 approved this pull request.
LGTM this is very cool
--
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
#1150 (review)
--
Here lies a toppled god —
His fall was not a small one.
We did but build his pedestal,
A narrow and tall one.
|
|
Although I like this proposal more than the other one, for reasons I will discuss in more detail there, I think this is a bad idea. Please hold off on merging this until further discussion. |
|
Okay, it looks like you closed the other one, so I'll move my comments here. |
|
I agree that ; seems like a better fit — it falls under “random macros” like ;~ —
…Sent from my iPhone
On Apr 16, 2019, at 5:41 PM, Anton Dyudin ***@***.***> wrote:
Making one last bid to use a ; rune for this, and leave =% open for
integration of something like /: into the hoon grammar :P
On 4/16/19, Ted Blackman ***@***.***> wrote:
> belisarius222 approved this pull request.
>
> LGTM this is very cool
>
>
>
> --
> You are receiving this because you are subscribed to this thread.
> Reply to this email directly or view it on GitHub:
> #1150 (review)
--
Here lies a toppled god —
His fall was not a small one.
We did but build his pedestal,
A narrow and tall one.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or mute the thread.
|
|
Or possibly to To elaborate on the rune category concern: |
pilfer-pandex
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have to say, I'm surprised and pleased. I expose you to Wadler for a few days, and here you are trying to add special syntax for monadic operations to Hoon. However, I want to urge restraint.
My biggest takeaway from #1145 is that everyone agrees that wet gates are incredibly cumbersome and difficult to work with. We have a few patterns for working around this difficulty, but these patterns make for repetitive code when trying to write in a monadic style.
I firmly believe more syntax is not the answer here, at least not yet. The answer is to fix wet gates. What will happen when we find we like applicative functors? More syntax? Alternatives? More syntax? Foldable and traversable?
What we need is a way to make generic functional programming work well. The main obstacle to this is the type system. In a world with HM type inference, you could just use ;: with your bind function, as I think you alluded to in the other pr. In such a world, I think we'd all more or less be opposed to the change suggested here.
I do understand that it will take time to create such a world, and in the meanwhile, you're stuck writing your aquarium code in a cumbersome way. I wish I had a quick answer for you, but I feel strongly this is not it.
|
It's also worth noting that when I was in college, I spoke with one of the original designers of Haskell, and he, to that day, was opposed to the addition of the do notation to haskell, saying it was a frivolous addition. For when merely translates to it's unclear what is gained by adding the first form directly to the grammar. The fact that there is special syntax here can also lead beginners astray. |
|
I disagree that wet gates are incredibly cumbersome and difficult to work with ^-^ They have some pitfalls, but can be very easily reasoned about mechanically, which I'll take any day over trying to puzzle out what types Hinley-Minler is failing to bidirectionally concoct properly.
Huh, for me it is perfectly clear: the number of glyphs in the code has been reduced by a factor of 3. This might sound somewhat hypocritical from a hoon perspective ofc, and I certainly concede that reserved words are significantly worse - but it doesn't make the gain any less obvious. |
Will do. I think Joe has thoughts too.
The argument for putting it in = is that it feels like "subject modification" when you're using it. It feels a lot like Unfortunately, most of the good
Wet gates have been recognized to be a pain for at least 5 years, and they're not fixed yet, despite multiple attempts to do so. I don't claim that it's impossible to fix them -- eg I think HM would likely fix the problems we've had with them, which is not to say it's necessarily a good idea -- but I don't think we should delay anything on the hope that they'll be fixed any time soon.
The same could be said of As for why this specific pattern is likely to be useful, my answer is that (1) we've often wished for monads, as evidenced by the fact that every 6 months somebody goes and half-implements them in a specific context and (2) it's the first pattern we've used that gets rid of decomposed state machines, and decomposed state machines are a fairly urgent problem (not in a threshold sense, it's just that programming in arvo is drastically slower and more bug-prone than it could be, and there's a significant cost to that).
It's not clear to me that better type inference will give a better experience for this than what this PR gives. Honestly, I like that you have to specify your bind operation and the intermediate types. You needed to give them names anyway, why not types? I feel that this style is significantly more readable than do notation because it includes the types. When I look at Haskell code in do notation, I don't know what anything is doing or what type it is because we don't explicitly name bind and the types. However, my point is not that we shouldn't switch to HM or otherwise improve type inference -- that's a whole other discussion which we're not ready to have yet. My point is that we shouldn't hold off on language improvements because there might some day be a better way to do it. Almost everything could reasonably be claimed to be close to changing, but you can't let that stop you from pushing the current system to its limits. For one, it bogs down progress by making you program more painfully, but more importantly you can't make a good decision as to whether a significant change like HM is worth it without pushing the current system to its limits. My general rule is that it's best to do things the right way given the current conditions until such time as a decision to change those conditions has actually been made. Additionally, even if we fix wet gates such that
I don't know idiomatic Haskell, so I can't judge whether do notation is a good idea there. But in hoon as it stands now, the expanded version is significantly more cumbersome and less readable. |
|
@joemfb suggested It's not great, but I think it's better than |
49c27e1 to
ce45aae
Compare
|
@pilfer-pandex You said IRL that you're less opposed to this than before; do you have any further objection to me merging this once I get feedback from people about naming it |
|
I'm in favor of this addition. To briefly recap some offline conversations: I don't think it makes sense to defer this until we've "fixed wet gates". I agree that the experience of parametric polymorphism is desirable, and that wet gates don't exactly provide it. I still think that wet gates are useful, and that the experience of using them can be improved, but I'll say no more until I have so demonstrated (and in the meantime, I sympathize with the idea of I do find this macro-expansion to be a little confusing, but I don't see any obvious way to improve it. It's certainly not any more confusing than |
|
I don't have anything more substantive to say than "this seems really neat!" But I do have a question! Is there a strong argument for the current wing ordering? ie, instead of: why don't we have: That seems closer to the expansion, and |
|
I could see it going either way, but this introduces a new variable to your subject, defined by the given type. As far as I can think, every time we do that it's the first argument to the rune except Additionally, putting the type second splits the bind from its argument. The type is an annotation, like
|
|
I think this is fine to merge in, based on how the above discussion unfolded. @philipcmonk was there anything else to add here? |
|
Based on further discussion in person, I think this is ok in the short term. |
Refer to #1145 for a discussion of motivation and some alternatives.
This introduces a new synthetic rune
=%. This:Expands to this:
The intended use case is monadic operations. Here's an idiomatic real-world example where I use it to boot two ships and have them
|hieach other. Note that each of these actions requires sending moves to another gall app and receiving multiple responses from that app.This assumes you have defined an explicitly parameterized monad that looks something like this:
Since bind is associative and monads compose, you can refactor this test:
This sort of composability of operations that include sending and receiving moves to other apps is something we've never properly had. This rune provides a convenient syntax to do that.
You can also use this with wet gates if you prepend
_. The gates also don't have to "bind" operations. For example:The usual cautions around wet gates apply. As is usual with wet gates, some extra casts may be necessary. In this case, the
(list (unit @))andsomelines are important to assign the correct types and faces.If the above code is confusing, consider adding some casts for documentation. This is too many, but it gets the point across: