class Steep::Interface::MethodType

def ==(other)

def ==(other)
  other.is_a?(self.class) &&
    other.type_params == type_params &&
    other.params == params &&
    other.block == block &&
    other.return_type == return_type &&
    (!other.location || !location || other.location == location)
end

def each_type(&block)

def each_type(&block)
  if block_given?
    params.each_type(&block)
    self.block&.tap do
      self.block.params.each_type(&block)
      yield(self.block.return_type)
    end
    yield(return_type)
  else
    enum_for :each_type
  end
end

def free_variables

def free_variables
  (params.free_variables + (block&.free_variables || Set.new) + return_type.free_variables) - Set.new(type_params)
end

def initialize(type_params:, params:, block:, return_type:, location:)

def initialize(type_params:, params:, block:, return_type:, location:)
  @type_params = type_params
  @params = params
  @block = block
  @return_type = return_type
  @location = location
end

def instantiate(s)

def instantiate(s)
  self.class.new(
    type_params: [],
    params: params.subst(s),
    block: block&.subst(s),
    return_type: return_type.subst(s),
    location: location,
    )
end

def subst(s)

def subst(s)
  s_ = s.except(type_params)
  self.class.new(
    type_params: type_params,
    params: params.subst(s_),
    block: block&.subst(s_),
    return_type: return_type.subst(s_),
    location: location
  )
end

def to_s

def to_s
  type_params = !self.type_params.empty? ? "<#{self.type_params.map{|x| "'#{x}" }.join(", ")}> " : ""
  params = self.params.to_s
  block = self.block ? " #{self.block}" : ""
  "#{type_params}#{params}#{block} -> #{return_type}"
end

def with(type_params: NONE, params: NONE, block: NONE, return_type: NONE, location: NONE)

def with(type_params: NONE, params: NONE, block: NONE, return_type: NONE, location: NONE)
  self.class.new(
    type_params: type_params.equal?(NONE) ? self.type_params : type_params,
    params: params.equal?(NONE) ? self.params : params,
    block: block.equal?(NONE) ? self.block : block,
    return_type: return_type.equal?(NONE) ? self.return_type : return_type,
    location: location.equal?(NONE) ? self.location : location
  )
end