Chaining of monads

Hi all, I’m trying something and I’m wondering if it’s possible.
Let’s say we have this:

      def first(a)
        Success(x: a)
      end

      def second(x:)
        Success(:anything)
      end

How would something like this be possible:

        first(1).bind(method(:second))

What I’m trying to do is return Success(hash) and bind that hash to named parameters for the next method.
Any ideas?

Hey Djordje, what you’re hinting at – and what I think you’re looking for – is function composition which can be pulled off using the Transactable gem. Example:

pipe 1, method(:first), method(:second)

Further details are explained in the links above, though.

Oh, interesting, thanks!
Is this related to dry-transaction in some way? I used to use it years ago and I’m wondering if this is similar.
Thank you very much for this, I got to look into it and learn how to use it.

Yep! So Transactable is an alternative approach to Dry Transaction with a strong focus on function composition. The concept is the same, though, where you compose multiple steps together using monads.

I looked into this subject for so long and googled lot of things but somehow missed existence of this gem entirely. Thank you very much!

You could achieve this with a built-in concept in dry-monads called do notation

class Operation
  include Dry::Monads[:result]
  include Dry::Monads::Do.for(:call)

  def call(a)
    result = yield first(a)
    result = yield second(**result)

    Success(result)
  end

  private

  def first(a)
    Success(x: a)
  end

  def second(x:)
    Success(:anything)
  end
end

Yeah, I know about do notation, but I find it cumbersome to come up with the names for every intermediate step and it somehow seems unnatural. Especially when the situation becomes more complicated and some “or” and “tee” cases are added, it soon loses readability in my opinion.
Thanks!