views:

44

answers:

1

As the title states, does Ruby allow Cartesian product types? I can't find anything on it anywhere.

Thanks

+2  A: 

Ruby doesn't allow types at all, at least not in the sense that you seem to be using the word "type". Therefore, it obviously doesn't support product types, either.

Ruby is a so-called "dynamically typed" language (using the pragmatic, programmer-jargon definition of the word "type") or an untyped language (using the mathematical, type-theoretic definition), so talking about "product types" simply doesn't make sense at all.

Or, if you want to, you can see a dynamically typed language as a statically typed language with only a single type which is the sum type of all dynamic types.

However, you can obviously construct values that would have a product type if Ruby had types at all:

class Tuple
  include Enumerable; include Comparable

  class << self
    alias_method :[], :new

    def call(length)
      class_name = :"Tuple#{length}"
      return const_get class_name if const_defined? class_name
      const_set class_name, Class.new(self) {
        (@length = length).times do |i| define_method :"_#{i+1}" do @ary[i] end end
      }
    end
  end

  def to_s; "(#{@ary.join(', ')})" end
  def inspect; "#<#{self.class} (#{@ary.map(&:inspect).join(', ')})>" end
  def to_ary; @ary.dup end
  def [](*args) @ary[*args] end
  def each(*args, &block) @ary.each(*args, &block) end

  def <=>(other)
    raise TypeError unless other.is_a? self.class
    raise TypeError unless each_with_index.all? {|el, i| other.instance_variable_get(:@ary)[i].instance_of?(el.class) }
    map.with_index {|el, i| el <=> other.instance_variable_get(:@ary)[i] }.find(0) {|cmp| !cmp.zero? }
  end

  def initialize(*args)
    raise ArgumentError unless args.length == self.class.instance_variable_get(:@length)
    (@ary = args).freeze
  end
end

This will give you a way to construct n-Tuples, which of course are special cases of product types. For example, this:

t3 = Tuple.(3)[1, :two, 'three']

will construct a triple with the tuple type (Fixnum, Symbol, String), which is a special case of the product type Fixnum × Symbol × String. But there is no way to represent and/or enforce those types in Ruby.

If you want to look deeper into type systems for Ruby, the Diamondback Ruby project is a good starting point. It includes tuple types, for example, which are an instance of product types.

Jörg W Mittag