Should `.to_result` respect Failure constraints?

When using .to_result inside a class that has defined Failure constrains, should the result respect those constrains.

Eg:

require "dry/monads/do"
require "dry/monads/result"
require "dry/monads/try"
require 'dry-types'

module Types
  include Dry.Types()
end

class DoSomething
  class Errors
    class BananaError; end
    class InternalError; end
  end

  include Dry::Monads[:result, :try]
  include Dry::Monads::Do.for(:call)

  Error = Types.Instance(Errors)
  include Dry::Monads::Result(Error)

  def call()
    Try {
      raise StandardError.new('BOOOM')
    }.to_result

  rescue  Dry::Monads::InvalidFailureTypeError => e
    puts "it didn't got rescued"
    # expected to catch here as the return is not one of the declared errors
    # Failure(#<StandardError: BOOOM>)
  end
end

puts DoSomething.new.call
# Failure(#<StandardError: BOOOM>)
require "dry/monads/do"
require "dry/monads/result"
require "dry/monads/try"
require 'dry-types'

module Types
  include Dry.Types()
end

class DoSomethingElse
  class Errors
    class BananaError; end
    class InternalError; end
  end

  include Dry::Monads[:result, :try]
  include Dry::Monads::Do.for(:call)

  Error = Types.Instance(Errors)
  include Dry::Monads::Result(Error)

  def call()
    Failure(StandardError.new('BOOOM'))

  rescue  Dry::Monads::InvalidFailureTypeError => e
    puts 'it got rescued'
  end
end

DoSomethingElse.new.call
# 'it got rescued'

Seems like the execution of .to_result is done in another scope, so the constrain is not applied. is it the expected behaviour? is there a way around it?

I don’t see a way how it would be possible. .to_result here is not connected to include Dry::Monads::Result(Error). It would be possible, though, to analyze returned values from methods and check them against the specified constraints. In fact, this may be a more reasonable design choice. It can be provided as a separate plugin/extension/gem on top of dry-monads. Personally, I abandoned using fixed error types in favor of passing arrays where the first element is a “type” of error:

def call(user_id)
  user = user_repo.find(user_id)
  unless user
    yield Failure[:user_not_found, user_id: user_id]
  end

  # ...

Maybe this approach can be combined with the idea of fixed-type errors. It could be

class UpdateUser
  include Result[
    :user_not_found, 
    :user_removed, 
    :no_permissions
  ]

  def call(...)
    ...
  end
end

At the moment, I don’t have the motivation to build something like that because I didn’t feel a practical need for something like this.