Skip to content

Commit

Permalink
Fix violation of functor laws
Browse files Browse the repository at this point in the history
Because `nil` exists as a singleton in Ruby, we need to preserve it when
yielded from `fmap` in order to obey the functor laws.

This ensures that:

    1.wrapped.fmap { nil }.unwrap_or(1)

Returns `nil` and not `1`.
  • Loading branch information
jferris committed Nov 13, 2014
1 parent 8160e18 commit 1aec2ee
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 1 deletion.
2 changes: 1 addition & 1 deletion lib/wrapped/present.rb
Expand Up @@ -84,7 +84,7 @@ def flat_map
#
# This makes it a functor.
def fmap
(yield unwrap).wrapped
Present.new(yield unwrap)
end

# Is this wrapped value equal to the given wrapped value?
Expand Down
29 changes: 29 additions & 0 deletions spec/wrapped_spec.rb
Expand Up @@ -179,6 +179,35 @@
it 'produces the blank for a wrapped nil' do
expect(nothing.fmap {|n| n+1}).to be_blank
end

it 'obeys the functor law: fmap id == id' do
expect(fmap(id).(just)).to eq(id.(just))
end

it 'obeys the functor law: fmap (f . g) == fmap f . fmap g' do
expect(fmap(compose(null, const(nil))).(just)).
to eq(compose(fmap(null), fmap(const(nil))).(just))
end

def fmap(f)
lambda { |x| x.fmap(&f) }
end

def const(x)
lambda { |_| x }
end

def id
lambda { |x| x }
end

def compose(f, g)
lambda { |x| f.call(g.call(x)) }
end

def null
lambda {|x| x.nil? }
end
end

describe Wrapped, 'equality' do
Expand Down

0 comments on commit 1aec2ee

Please sign in to comment.