Created
April 9, 2013 17:04
-
-
Save Whitespace/5347441 to your computer and use it in GitHub Desktop.
Revisions
-
Whitespace created this gist
Apr 9, 2013 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,136 @@ require "minitest/autorun" module Monad def return(val) self.class.new(val) end def bind(&block) self.return yield @value end end class Identity include Monad attr_reader :value def initialize(value) @value = value self end def ==(value) @value == value end end describe Identity do it "#bind is a left-identity with respect to return" do value = rand(100000) monad = Identity.new(value) monad.bind do |v| Identity.new(v) end.must_equal(monad) end it "#return is a right-identity with respect to bind" do value = rand(100000) rand1 = rand(100000) f = lambda { |v| v + rand1 } monad = Identity.new(value) monad.bind(&f).must_equal f.call(value) end it "#bind is associative" do value = rand(100000) rand1 = rand(100000) rand2 = rand(100000) f = lambda { |v| v + rand1 } g = lambda { |v| v + rand2 } monad = Identity.new(value) monad.bind do f.call(g.call(value)) end.must_equal monad.bind(&f).bind(&g) end end module Just def just self end end class Nothing def self.just self end def just self.class end end class Object include Just end class Maybe include Monad attr_reader :value def initialize(value) @value = value end def fetch @value.just end def bind(&block) self.return case fetch when Nothing then Nothing else yield @value end end def ==(value) fetch == value end end describe Maybe do it "#bind is a left-identity with respect to return" do value = rand(100000) monad = Maybe.new(value) monad.bind do |v| Maybe.new(v) end.must_equal(monad) end it "#return is a right-identity with respect to bind" do value = rand(100000) rand1 = rand(100000) f = lambda { |v| v + rand1 } monad = Maybe.new(value) monad.bind(&f).must_equal f.call(value) end it "#bind is associative" do value = rand(100000) rand1 = rand(100000) rand2 = rand(100000) f = lambda { |v| v + rand1 } g = lambda { |v| v + rand2 } monad = Maybe.new(value) monad.bind do f.call(g.call(value)) end.must_equal monad.bind(&f).bind(&g) end end