deterministic icon indicating copy to clipboard operation
deterministic copied to clipboard

Monad operators

Open gilbert opened this issue 10 years ago • 0 comments

I'm trying to use the equivalent of >> in haskell, which discards the result of the previous call:

require 'deterministic'

class X
  extend Deterministic

  def self.util(message, ctx)
    Success(message)
  end
end

class Y
  include Deterministic

  def run(input)
    do_something(input) >> X.method(:util).to_proc.curry['it worked']
  end

  def do_something(input)
    Success(input)
  end
end

y = Y.new
puts "RESULT: #{y.run(true).inspect}"

...but using >> requires the util method to accept an additional parameter, making things less composable.


I have an idea for making Deterministic more streamline. If you're willing to make a breaking change, I think it might be better to use the three operators >=, >, and <. Although it's not nearly as cool as using >>, the advantage is they all have the same precedence.

Here is what I think each one should do:

  • >= is haskell's >>=
  • > is haskell's >>
  • < is Deterministic's pipe

Note that try is no longer an operator. I think this is ok because, thanks to functional programming, we can easily abstract it into its own method:

require 'deterministic'

class AttemptExample
  include Deterministic

  def attempt(method_name)
    lambda do |ctx|
      begin
        self.send(method_name, ctx)
      rescue Exception => e
        Failure(e)
      end
    end
  end

  def run(input)
    # Equivalent to the current do_something(input) >= method(:fail)
    do_something(input) >> attempt(:fail)
  end

  def do_something(input)
    Success(input)
  end

  def fail(input)
    raise "BOOM"
  end
end

a = AttemptExample.new
puts "RESULT: #{a.run(true).inspect}"

What do you think? I think this will make Deterministic a great joy to use! I am also open for discussion.

gilbert avatar Aug 29 '14 17:08 gilbert