-
Notifications
You must be signed in to change notification settings - Fork 376
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
Foldable / Traversable #68
Conversation
Works for me 👍 |
I've got some questions, for clarity. Why is If it's for the Or is there some other reason? |
the Foldable and Functor specficiations. | ||
|
||
1. `t(u.traverse(f, of))` is equivalent to `u.traverse(function(y){ return t(f(y)) }, of)` | ||
where `t :: (Applicative f, Applicative g) => f a -> g a` (naturality) |
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.
We might want to stick with non-haskell-esque type signatures.
Maybe just state:
t
is a function that takes anApplicative
of some type and returns anApplicative
for another (possibly the same) type.
Although, this is still more descriptive than what the other algebras say 👍
EDIT: Or maybe, we should keep this as an improvement. Yeah, I think having both would be best.
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.
What if we say:
where
t
is a natural transformation
I believe that's all we need to express in the law.
I 100% agree that Hindley-Milner is probably not the best way to express this to javascript developers coming from all different backgrounds. (scala/f#/haskell/clojure)
Also, thanks tremendously for taking the time to make this! 👍 |
I've mostly been lurking here, but I'm confused by the use of |
Yeah, Anyway, it's usually got a haskell definition like so: newtype Compose f g x = Compose (f (g x)) So the kinds of What this means is you'd use it like: In js you'd probably do something like: var Compose = function(x) {
this.val = x;
];
Compose.prototype.map = function(f) {
return new Compose(this.val.map(function(y) { return y.map(f); }));
};
... Does that help? |
Thanks. Since I first posted, I've been able to mostly work out what Compose must do, but it's nice to have a simple explanation. My bigger concern is having this undefined term in the specification. I'm in the process of trying to implement some of the standard Functors and Monads in Ramda and would like to see if we can follow the fantasy-land spec. Having the spec grow while we're at it might be a bit disheartening, although I'm not sure it will really affect us. But mostly I'm concerned about having the specification depend on such an undefined term. |
Hi @joneshf Glad to help and I appreciate the discussions on this. I'm very excited to try to get these classes into the spec (they're working on getting these into base for haskell as well). So it turns out, I got a bit confused about the monoid superclass. I saw the graphic from typeclassopedia: http://www.haskell.org/haskellwiki/File:Typeclassopedia-diagram.png fold :: Monoid m => t m -> m
fold = foldMap id
foldMap :: Monoid m => (a -> m) -> t a -> m
foldMap f = foldr (mappend . f) mempty But it turns out the monoid constraint is not on the foldable structure, but instead the possible monoid inside. If it doesn't have a monoid inside on a call to So I can update the spec (and graphic) to remove the monoid superclass as it's unnecessary. |
@CrossEye I dislike these random objects as well. I was simply porting it from the previous haskell work. As you've already figured out fmap(fmap(f), Some([x])) vs fmap(f, Compose(Some([x])) Without the Which is indeed equivalent! Correct me if I'm wrong, but I believe Incidentally, I've come to realize that mismatching I don't mind I'll make these changes now if we're down. |
I couldn't possibly correct you on this. My Haskell experience is confined to a single reading of a beginners' book. (LYAH). I've learned a fair bit about what it does, a reasonable amount about how it works. I can mostly figure out Haskell code when I see it, but I have definitely not internalized the ideas.
Even here, I don't think I agree, although it's less of an issue than Compose. I would rather the spec holds together entirely as a spec, without ever bringing in such implementation details. Also the one @puffnfresh included is called
I have no objections; I'm still too new to this stuff. I was hoping that this was a pretty well finished spec when I started working on my implementations after the Hardcore FP class you taught a few weeks ago. Alas... |
I hear you on the concerns. As far as changes go, I wouldn't be worried about the spec evolving. The previous algebra's don't have any reason to change and new ones will just build on the behavior. Foldable and Traversable are newer, but they have been solid for years and proven so useful they've become part of every day idiomatic code. It's just this initial definition in js that's a little tricky since it's not a 1:1 port from scala or the haskell. I think it's great that we can build on the spec by adding new algebras that work with the previous ironclad ones. What I'm trying to say is that Ramda can use the spec and shouldn't be in any danger of having to redo work. For Derivations are another matter though. For instance, Functor can be derived from Traversable with the help of function(f){ return this.traverse(function(x){ return new Id(f(x)) }, Id.of).value; } Foldable can also be derived from Traversable in a similar fashion with var foldMap = function(f, of) {
return this.traverse(function(x){ return new Const(f(x)) }, function(x){ return Const.of(of(x)) }).value;
}
t.prototype.reduce = function(f, acc) {
return this.foldMap(function(x){
return new Endo(function(y){ return f(y,x); })
}, Endo.of).value(acc);
}
So if someone can define That's pretty ridiculous for the spec, I realize. But this is fantasy land - land of the free. Land where everything plugs together generically. Satisfaction guaranteed. Perhaps there can be a derivation library that just extends the prototypes for us. At that point we wouldn't need to add all that to the specs. That doesn't solve the laws issue though. I don't know how to get around the fact that I need a neutral applicative functor to express the identity law. |
Well, here's an idea. To go on @phadej's comment, it would be nice to have some reason to depend on the spec. For these types that are simple enough, and also used in the laws, why not put them into the So, we'd have an actual reason to have this spec as a dependency, and we'd have a reason to actually start versioning it properly. Not to mention, we could have these laws where data types like In other news, I think this PR should be accepted. Would be great to have |
I think that's a terrific idea. I can put I was thrilled to wake up this morning and find I'd been added as an owner. I feel odd about merging my own pull request so I'll hold off on that, but Yippee! Can anyone help with that graphic as an svg? Not sure how the old one was created... |
I have no experience with it, but that seems to be a MetaPost document. There is a previewer online, and I can use it to regenerate the SVG and PNG, and I imagine it wouldn't be too hard to reverse-engineer the format (figures/dependencies.mp) But I also don't think that keeping with MetaPost is that important, unless someone who knows it is still around... |
Thinking about the dependency on the spec issue... Perhaps it could be a dev dependency for quickchecking compliance. The spec would include Just thinking out loud, but I believe the dev dependency might be the way to go. |
I was thinking of something similar with the quickcheck, though using purescript. There was a library that did something similar with the laws a while back, can't remember what it was at the moment though. |
That would solve the dep issue and the |
What's the status of this pull request? |
I'm down to merge if others are. I could also break this into just Foldable. Is it blocking ramda? |
it ain't blocking me. it would be nice to have for ramda-fantasy |
I'm happy with this, 👍 for merge from me |
You had my vote last year ;). |
Right then let's do this! |
🎉 |
🍰 |
|
||
1. `x` is the initial accumulator value for the reduction | ||
|
||
### Traversable |
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.
@DrBoolean May I have an example of Traversable and Sequence? Pretty pls?
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.
Here's a gist of the laws: https://gist.github.com/DrBoolean/c4949a0f4b8f9ba8261f
A quick example would be:
[Promise.of(1), Promise.of(2)].sequence(Promise.of)
//=> Promise([1,2])
It turns [Promise]
to Promise []
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.
Oh cool. Thanks sir.
Going over the gist now.
Not sure if everything is how we want it yet, but thought i'd create this pull request to make it easier to see the changes.