-
Notifications
You must be signed in to change notification settings - Fork 384
Add Functional Programming - Generics as Type Classes #249
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
Conversation
Hmm, the errors seem to be caused by broken links. I thought relative links would work in mdbook. Any guidance on how to fix those? |
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 think it's just that the patterns
subdirectory was missing
This is related to #100 isn't it? Maybe you can take the links from there, I posted some articles in it, that describe the pattern. |
f41f78b
to
8a48392
Compare
Thanks, @simonsan. I actually missed that PR somehow. I have added the bottom of the two links you mentioned. Now my question is, how do I break up the link for the hard wrap limit? It is longer than 80 characters by itself. |
Maybe this one is also a nice addition to |
The second link makes sense to me, @simonsan, and seem to cover the type theory in more depth. I also put in a small wording change to be more precise, and helpful if people Google this. I think it's a solid first version that is ready to merge, unless you have other additions. |
I need to give it a full read still, haven't completely reviewed it due to time constrains and just helped you fix the CI tests. Will take care of it the next two days. Cheers. |
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.
@marcoieni @pickfire Want to give it a read as well?
functional/stateful-types.md
Outdated
|
||
Here is what that looks like: | ||
|
||
```rust,ignore |
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 would prefer to remove this ignore
flag, even if it requires copy pasting from previous code blocks.
What other people think about this?
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.
Could be nice to have a working example here, indeed. So people can copy and paste it and try it out/play around with it.
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 only did that to avoid repeating all the typing. I can easily put that back in and make it work.
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.
Hmm, this is turning out to be trickier than I thought. I may have to refactor the example to make it simple enough. That will take me a bit.
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.
If you want to you can do that in another PR as well (regarding removing the ignore
). It would be nice to have a working example that is checked, but not always necessary. Also this is quite complex so I'm fine with just refactoring it at a later stage, maybe even by someone else. @marcoieni thoughts?
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.
It's up to jhwgh. If you want you can do it in another PR :)
What's the advantage of using this approach for state machines with respect to the one covered by the rust book ? |
The main advantage over the book, @marcoieni, is that this allows for shared data and IMO more readable shared impls. I will type up that explanation in the PR. |
7bef713
to
dc4ab22
Compare
functional/stateful-types.md
Outdated
|
||
Here is what that looks like: | ||
|
||
```rust,ignore |
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.
If you want to you can do that in another PR as well (regarding removing the ignore
). It would be nice to have a working example that is checked, but not always necessary. Also this is quite complex so I'm fine with just refactoring it at a later stage, maybe even by someone else. @marcoieni thoughts?
functional/stateful-types.md
Outdated
interp.compile_script("print('2 + 2')").unwrap(); | ||
interp.exec().unwrap(); | ||
} | ||
``` |
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.
Example seemed complicated. If someone like me who had no experience with state machine, this will be hard to understand. Just wondering could there be a simpler example?
Say, empty letter -> written letter -> closed letter?
functional/stateful-types.md
Outdated
struct Interpreter<S: State> { | ||
// same fields for execution, but now add: | ||
state_data: S, | ||
} |
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.
Seemed extra to me. Why not just Interpreter
-> LoadedInterpreter
-> ReadiedInterpreter
or something similar since they won't share common stuff?
Or maybe this is just to show <S: State>
? Or maybe we can show both methods.
functional/stateful-types.md
Outdated
|
||
```rust,ignore | ||
fn main() { | ||
let mut interp = Interpreter::<Init>::default().init(); |
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.
Having this turbofish is the downside of what I mentioned. Not ergonomics and what if user does Interpreter::<Loaded>::default()
instead? At least default isn't there in this case which is safe.
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.
The default only being in the init state is precisely what I intended, for that exact reason.
I agree it's clunky, but also I think it's reasonable to recomment. If you don't put the turbofish in at all, I think the current stable has a good suggestion to lead you in the right direction.
Co-authored-by: Marco Ieni <[email protected]>
I have a couple more review comments to go, but I am getting close.
Done.
On other PRs I saw maintainers doing "merge commits" with master, which usually creates a giant mess in git. I will keep that in mind that you always squash, and not worry about it.
Ah, that makes sense. I will fix it. |
The |
Co-authored-by: Marco Ieni <[email protected]>
Co-authored-by: Marco Ieni <[email protected]>
Cool! I'll also read through it again in the next days. <3 |
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.
This is great! I approved it. simonsan, merge this if it looks good to you once you have read it :)
Thanks, @marcoieni! I unfortunately could not think of an easy constructor for main, but I think this example is clear enough as it is. |
Nice, thank you! :) |
I put this under functional languages, since it is really an example of the concept of "type classes" in Rust. If this specific example is more of a design pattern, I would be happy to move it.
If no one beats me to it, I should be able to fix the two FIXMEs at the bottom sometime next week.