Sunday, December 03, 2006

Monads In Ruby Part 1.5: Identity

So after chatting in #haskell on freenode it became apparent that my Identity monad was kind of a cheat. It wasn't a function from types to types. So I present here for comment, a modified version, that pretends that ruby has parametric types:

% cat identity.rb
$implementation_detail = {}
def Identity(klass)
$implementation_detail[klass] ||= Class.new do
define_method :initialize do |obj|
@obj = obj
end

define_method :m_bind do |f|
r = f.call( @obj )
raise TypeError, "Bind did not type check" unless r.kind_of? Identity(klass)
r
end

(class << self; self; end).class_eval {
define_method :m_return do |obj|
raise TypeError, "#{obj} not instance of #{klass}" unless obj.kind_of? klass
self.new( obj )
end

define_method :name do
"Identity(#{klass})"
end

alias_method( :to_s, :name )
alias_method( :inspect, :name )
}
end
end

p Identity(Array).m_return( [1, 2, 3] ).m_bind( lambda do |a|
Identity(Array).m_return( [3] + a[1..-1] )
end)




% ruby identity.rb
#<#:0x1eaff0 @obj=[3, 2, 3]>

No comments: