Skip to content

Instantly share code, notes, and snippets.

@AndrewRadev
Created November 20, 2010 22:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AndrewRadev/708225 to your computer and use it in GitHub Desktop.
Save AndrewRadev/708225 to your computer and use it in GitHub Desktop.
require 'pp'
class Monad
class Wrapper
def initialize(monad)
@monad = monad
@lets = {}
end
def let(name, value)
@lets[name] = @monad.new(value)
end
def pure(x)
@monad.new(x)
end
def method_missing(m, *args, &block)
@lets[m]
end
end
attr_reader :core
def initialize(x)
if x.respond_to? :value # it should be a monad
@core = x.value
else
@core = x
end
end
def self.lift(op, *args)
raise "Lift not implemented"
end
def method_missing(m, *args, &block)
self.class.lift(m, *([self] + args))
end
def self.execute(&block)
Wrapper.new(self).instance_eval(&block)
end
end
class ListMonad < Monad
def self.lift(op, *args)
left, right = args # assume two items
left.core.map do |x|
if right.kind_of? ListMonad
right.core.map do |y|
x.send op, y
end
else
x.send op, right
end
end.flatten
end
end
m = ListMonad.execute do
let :x, [1,2,3]
let :y, [3,4,5]
z = x + y
pure z
end
pp m.core
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment