Sha256: cdcabccb7319e09ec71f26ea1548e24abfd71b88abf9e457eb6b42ffb323e022

Contents?: true

Size: 1.6 KB

Versions: 1

Compression:

Stored size: 1.6 KB

Contents

require "funkr/adt/matcher"

module Funkr

  # Very rought Algebraic Data Types. A class inheriting from ADT can
  # declare constructors with #adt
  class ADT

    MATCHER = Funkr::Matchers::SafeMatcher

    def initialize(const, *data)
      @const, @data = const, data
    end

    # Declare ADT constructors, for example :
    #   class Maybe < ADT;  adt :just, :nothing; end
    def self.adt(*constructs)
      build_adt(constructs)
      build_matcher(constructs)
    end

    def self.matcher; @matcher; end
    
    # Match your ADT against its constructors, for example :
    #   a = Maybe.just("hello")
    #   a.match do |on|
    #     on.just{|x| puts x}
    #     on.nothing{ }
    #   end
    def match(&block)
      self.class.matcher.match_with(normal_form, &block)
    end

    def unsafe_const; @const; end
    def unsafe_data; @data; end

    def to_s
      format("{%s%s%s}",
             @const,
             @data.any? ? " : " : "",
             @data.map(&:inspect).join(", ") )
    end
    
    
    def ==(o)
      case o
      when ADT then self.normal_form == o.normal_form
      else false
      end
    end

    def normal_form; [@const, *@data]; end

    private

    attr_reader :const, :data
    
    
    def self.build_adt(constructs)
      constructs.each do |c,*d|
        define_singleton_method(c) do |*data|
          self.new(c,*data)
        end
        define_method(format("%s?",c).to_sym) do
          const() == c
        end
      end
    end
    
    def self.build_matcher(constructs)
      @matcher = Class.new(MATCHER) do
        build_matchers(constructs)
      end
    end

  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
funkr-0.0.40 lib/funkr/adt/adt.rb