[ANN] MLTypes: ML-style qualified unions for ruby

Discussion in 'Ruby' started by Logan Capaldo, Sep 20, 2005.

  1. I've always liked ML-style languages for declaring new types, and I
    thought hey, let me try to do that in ruby, its already got a case
    statement that reminds me of ML. So on with the examples:

    % cat example.rb
    require 'mltypes'

    deftype :List do
    :Cons.of( :first => :Object, :rest => :List) | :End
    end

    deftype :Tree do
    :Leaf.of:)data => :Object) | :Branch.of( :data
    => :Object, :left => :Tree, :right => :Tree )
    end

    def print_list(list)
    case list.tag
    when :Cons
    puts list.first
    print_list(list.rest)
    when :End
    end
    end


    def print_tree_inorder(tree)
    case tree.tag
    when :Leaf
    puts tree.data
    when :Branch
    print_tree_inorder(tree.left)
    puts tree.data
    print_tree_inorder(tree.right)
    end
    end

    ls = List.Cons:)first => 1, :rest => List.End)
    ls = List.Cons( :first => "Hello", :rest => ls )
    print_list ls

    tree = Tree.Branch( :data => 2, :left => Tree.Leaf( :data =>
    1 ), :right => Tree.Leaf( :data => 3 ))

    print_tree_inorder(tree)

    __END__

    Not bad huh?

    The other interesting thing to note (for me anyway is)

    deftype :MyBoolean do
    :Yes | :No # bar works here
    end

    :maybe | :so # not here though
    NoMethodError: undefined method `|' for :maybe:Symbol
    from (irb):6

    So it shouldn't mess up any existing stuff that relies on Symbol not
    having |.
    OTOH, its kind of heavy -handed (ie if you defined | for something
    else it will mess stuff up completely. Just keep that in mind)

    Now here is the code that does all this fun.

    % cat mltypes.rb
    module MLTypes
    class Alternation
    def initialize(alts = [])
    @alts = alts
    end
    def |(other)
    @alts << other
    self
    end

    def alternatives
    @alts
    end
    end
    class TaggedTuple
    def initialize(tag, pairs)
    @tag = tag
    @pairs = pairs
    end

    def |(other)
    Alternation.new([self, other])
    end

    def tag
    @tag
    end

    def pairs
    @pairs
    end
    end
    end
    def deftype(name)
    res = nil
    begin
    Symbol.class_eval {
    define_method:)"|") do |other|
    MLTypes::Alternation.new([self, other])
    end

    define_method:)of) do |pairs|
    MLTypes::TaggedTuple.new(self, pairs)
    end
    }
    res = yield
    ensure
    Symbol.class_eval {
    remove_method:)"|") rescue nil
    remove_method:)of) rescue nil
    }

    end

    Object.const_set(name.to_s, Class.new)
    klass = Object.const_get name

    klass.class_eval {
    define_method:)tag) do
    @tag
    end
    m = instance_method:)method_missing)

    define_method:)method_missing) do |*args|
    if not @state.nil? and @state.has_key?(args[0])
    @state[args[0]]
    else
    m.bind(self).call(*args)
    end
    end

    res.alternatives.each do |enum|
    obj = klass.new
    metaklass = (class << self; self; end)
    if enum.kind_of?(MLTypes::TaggedTuple)
    metaklass.class_eval {
    define_method(enum.tag) { |
    args|
    state = {}
    enum.pairs.keys.each
    do |key|
    raise
    TypeError, "Expected #{enum.pairs[key]} got #{args[key].class}"
    unless args[key].kind_of? Object.const_get(enum.pairs[key])
    state[key] =
    args[key]
    end
    res =
    klass.class_eval { new }
    res.instance_eval
    { @state = state; @tag = enum.tag }
    res
    }
    }
    else # regular enum
    obj.instance_eval { @tag = enum }
    metaklass.class_eval {
    define_method(enum) do
    obj
    end
    }
    end
    end

    class << self
    private :new
    end
    }

    end

    __END__
     
    Logan Capaldo, Sep 20, 2005
    #1
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Frank Drebin

    Re: fully qualified domain name

    Frank Drebin, Aug 26, 2003, in forum: ASP .Net
    Replies:
    0
    Views:
    621
    Frank Drebin
    Aug 26, 2003
  2. Jacob Crossley
    Replies:
    0
    Views:
    425
    Jacob Crossley
    Apr 2, 2004
  3. Szabolcs Borsanyi

    Pointer to qualified poitner to qualified object

    Szabolcs Borsanyi, May 30, 2008, in forum: C Programming
    Replies:
    13
    Views:
    593
    Keith Thompson
    Jun 8, 2008
  4. Ken Varn
    Replies:
    0
    Views:
    539
    Ken Varn
    Apr 26, 2004
  5. Austin Ziegler
    Replies:
    0
    Views:
    102
    Austin Ziegler
    Aug 8, 2007
Loading...

Share This Page