-
Notifications
You must be signed in to change notification settings - Fork 93
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
Many seems to be broken #8
Comments
I also tried another approach, changing the Monad.within method: def within(&block)
and_then do |value|
self.class.new(block.call(value))
end
end Which, in turn, breaks the eventually specs ^^°:
Because it tries to initialize the monad giving it a block, not a proc as a parameter. I'm beginning to think part of the factoring went wrong somewhere, but I'm not yet sure what and where. I'll be trying to find that when I'm rested. |
Hi. Can you describe what exactly you are expecting from your code? Maybe you have more meaningful example. I don't understand what do you think is broken... |
Use more delicate way (from ActiveSupport) to wrap an array instead of just putting value into array anyways.
Hi @sclinede, it's been a while so I may be fuzzy on the details, but I submitted a pull request to fix the thing I think was broken. What was broken? # an author writes books...
Author = Struct.new(:books)
# ...a book contains chapters...
Book = Struct.new(:chapters)
# ...here are some books, with or without chapters...
books = [
Book.new([1, 2, 3, 4]),
Book.new([5, 6, 7]),
Book.new([]),
Book.new([8, 9])
]
# ...here are authors with or without books...
authors = [
Author.new(books),
Author.new([])
]
# ...I'm trying to use the Many monad to extract the chapters from all the books from all the authors
Monads::Many.new(authors).books.chapters.values
# here is what I expected to obtain:
=> [1, 2, 3, 4, 5, 6, 7, 8, 9]
# but what I actually got is the following error:
# NoMethodError: undefined method `chapters' for #<Array:0x0055f546fb4e88>
# from lib/monads/monad.rb:11:in `public_send'
# from lib/monads/monad.rb:11:in `block in method_missing'
# from lib/monads/monad.rb:5:in `call'
# from lib/monads/monad.rb:5:in `block in within'
# from lib/monads/monad.rb:21:in `call'
# from lib/monads/monad.rb:21:in `block in ensure_monadic_result'
# from lib/monads/many.rb:10:in `map'
# from lib/monads/many.rb:10:in `and_then'
# from lib/monads/monad.rb:4:in `within'
# from lib/monads/monad.rb:10:in `method_missing' Now here's why I think it went wrong, and how I fixed it: def and_then(&block)
block = ensure_monadic_result(&block)
# this line looks wrong, because flat_map doesn't do what was expected of it
Many.new(values.map(&block).flat_map(&:values))
end
# when I do this:
authors.map { |a| Monads::Many.from_value(a.books) }.flat_map(&:values)
# I get:
=> [[#<struct Book chapters=[1, 2, 3, 4]>, #<struct Book chapters=[5, 6, 7]>, #<struct Book chapters=[]>, #<struct Book chapters=[8, 9]>], []]
# But, wait, I hear you ask, this is not flat, not at all!!!
# No, it isn't. flat_map didn't do (map.flatten), it did (flatten.map)!
# Well then, instead of relying on flat_map, like this:
Many.new(values.map(&block).flat_map(&:values))
# We should do a map, then flatten it, likewise:
Many.new(values.map(&block).map(&:values).flatten) |
OK, now I see. I think map + flatten is right solution. @tomstuart, what about you? |
First of all, thanks for your talk about Ruby monads, it blew my mind ^^
I've been trying to imitate your logic as a TDD exercise, and was comparing what I was writing to your code and found a difference puzzling me in the "Many" monad.
When I'm trying to use yours, I find that:
Ends up in a:
I thought it had something to do with the Many.from_value method and tried a quick-and-dirty fix with:
It makes the method_missing do its job and return the subelements expected, though I find one test (
spec/monads/many_spec.rb:49
the one that verifies that Many.from_value wraps the value in an array before wrapping it in the monad) fails.I'm a bit unsure on what to do to fix this, so I thought I'd let you know ^^°
Again, thanks for the awesome talk and ideas.
The text was updated successfully, but these errors were encountered: