Live data from Hacker News

Refactoring Ruby with Monads

codon.com

11–20 of 41 posts

Re: Refactoring Ruby with Monads

#11
I don't plan on rewriting my Rails apps, but the talk is certainly food for thought. At the very least this is a nice explanation of Ruby metaprogramming techniques; pair it with Paolo Perrotta's "Metaprogramming Ruby" and you'll have a good handle on the subject.

Re: Refactoring Ruby with Monads

#12

Please don't actually do this. Ruby is not a functional language, if your project really needs to be functional all the way through just use Haskell or whatever. Otherwise just pull out the parts of your code would benefit from being expressed in functional style into a module and work on implementing a proper DSL.

From the conclusion: > Now, to be clear, I’m not saying you should immediately refactor all your Rails applications to use monads; I’m just using Ruby as a tool to explain an interesting idea about programming, not giving you a best practice for all your Ruby code. However, it’s good to know about techniques like this! And in some cases, by applying the power of monads wisely, we can untangle nested callbacks, make p…

Yes, the author agrees with me that it's an intellectual exercise. I just wanted to underline that.

Rubyists are a clever bunch, if you find yourself writing the same code over and over again, chances are somebody's already figured out how to refactor it appropriately, tucking away the details behind an intention-revealing module.

A better way to refactor code is in using Ruby's built-in metaprogramming abilities. Metaprogramming Ruby is the best book to show you how.

http://www.amazon.com/Metaprogramming-Ruby-Program-Like-Face...

Re: Refactoring Ruby with Monads

#13
This should be "Refactoring Ruby with Applicative Functors". The common interface for the so-called "monads" here is a subset of that of an applicative functor [1]; the fact that the types discussed could also support monad definitions (and that in some other languages, the applicative functor definition would piggy back on the monad definition) isn't really relevant.

[1] Comparing the listed Ruby to Haskell, .from_value is "pure", #within is "fmap", and there's no real equivalent of .

Re: Refactoring Ruby with Monads

#14

Please don't actually do this. Ruby is not a functional language, if your project really needs to be functional all the way through just use Haskell or whatever. Otherwise just pull out the parts of your code would benefit from being expressed in functional style into a module and work on implementing a proper DSL.

Monads are useful even in imperative languages. They're just a context with a way of specifying how actions get chained together. Scala, Swift, and a number of other imperative languages have adopted monads (like Maybe) to great effect. Conversely, the state monad (for example) has seen less adoption. Probably because it's a little difficult to grasp, and imperative languages just rely on mutable state for a similar…

> Scala, Swift, and a number of other imperative languages have adopted monads (like Maybe) to great effect.

Much of the use of "monads" in many other languages -- and particularly all the examples here -- really rely only on that subset of monad functionality that defines applicative functors.

> Conversely, the state monad (for example) has seen less adoption.

The use of the state monad really relies on it being a monad and not a mere applicative functor; I'm not sure if that's related, but I think that applicative functors are an easier thing to wrap your head around than monads.

Re: Refactoring Ruby with Monads

#15
post #10

Earlier quoted context omitted.

It's a style and design problem. Ruby is designed to make it easier on the developer when he's trying to do stuff. Part of that design is being able to read the code. If I went into a codebase and saw classes being used for functional constructs instead of repositories for holding state, I'd quietly close the project down and find another gem. Ruby has a way to do immutability. It has methods to do common stuff like…

I'm sorry, but I really don't follow at all. You call this approach heavy handed when in fact it's relatively small amount of source code that makes for much more readable developer code down the line. To me, Maybe seems like a much lighter touch than monkey patching Object. And I don't understand your insistence that you're "writing another language" in Ruby by using a few functional constructs. For a language that…

I went through HtDP and loved it, it helped me gain a data-centric view on programming, and the lessons carried very well into my later Ruby career. I looked at Arc and liked the idea.

I like Ruby better than Lisp. It's hard to explain why. One of the reasons why I like to argue about this sort of thing on the Internet is because it helps me isolate the subtler qualities of different styles of programming.

I like Ruby because you can build a community around it, in a way that I don't think you can build one around Lisp, at least not like the one you find in Ruby, with the massive quantities of libraries and such.

Lisp is too free-form. You almost never need the power it gives you, and it encourages people to build their own language features where the problem being solved could probably do with a more conventional approach.

Ruby hits a sweet spot, enough dynamism to where you don't feel constrained, not so much that you can't easily reason about code. Code as data is a neat idea, but code needs to be read by humans and that's the harder task.

Re: Refactoring Ruby with Monads

#16

This should be "Refactoring Ruby with Applicative Functors". The common interface for the so-called "monads" here is a subset of that of an applicative functor [1]; the fact that the types discussed could also support monad definitions (and that in some other languages, the applicative functor definition would piggy back on the monad definition) isn't really relevant. [1] Comparing the listed Ruby to Haskell, .from_v…

`#and_then` is the monadic bind operation `>>=`; applicatives don't have this operation in general.

Re: Refactoring Ruby with Monads

#17

Please don't actually do this. Ruby is not a functional language, if your project really needs to be functional all the way through just use Haskell or whatever. Otherwise just pull out the parts of your code would benefit from being expressed in functional style into a module and work on implementing a proper DSL.

Monads are useful even in imperative languages. They're just a context with a way of specifying how actions get chained together. Scala, Swift, and a number of other imperative languages have adopted monads (like Maybe) to great effect. Conversely, the state monad (for example) has seen less adoption. Probably because it's a little difficult to grasp, and imperative languages just rely on mutable state for a similar…

[deleted]

Re: Refactoring Ruby with Monads

#18

Earlier quoted context omitted.

Monads are useful even in imperative languages. They're just a context with a way of specifying how actions get chained together. Scala, Swift, and a number of other imperative languages have adopted monads (like Maybe) to great effect. Conversely, the state monad (for example) has seen less adoption. Probably because it's a little difficult to grasp, and imperative languages just rely on mutable state for a similar…

> Scala, Swift, and a number of other imperative languages have adopted monads (like Maybe) to great effect. Much of the use of "monads" in many other languages -- and particularly all the examples here -- really rely only on that subset of monad functionality that defines applicative functors. > Conversely, the state monad (for example) has seen less adoption. The use of the state monad really relies on it being a m…

No. #and_then here is monadic bind (>>=), and is necessary for all three use cases he described - nested nil checks, nested iteration, nested IO actions/callbacks.

Re: Refactoring Ruby with Monads

#19
For the author's toy example, I don't see how this is better than using begin... rescue.

  def weather_for(project)
    begin
      project.creator.address.
        country.capital.weather
    rescue NoMethodError
      nil
    end
  end
Post reply on HN