Skip to content

Instantly share code, notes, and snippets.

@denisdefreyne
Created February 5, 2011 14:00
Show Gist options
  • Save denisdefreyne/812470 to your computer and use it in GitHub Desktop.
Save denisdefreyne/812470 to your computer and use it in GitHub Desktop.
## Implementation
class Arrow
class Either
attr_reader :obj
def initialize(obj)
@obj = obj
end
def eql?(other)
return false unless [ Arrow::Left, Arrow::Right ].include?(other.class)
return false unless self.class == other.class
@obj == other.obj
end
def hash
super ^ @obj.hash
end
end
class Left < Either
end
class Right < Either
end
def initialize(&fun)
@fun = fun
end
def self.swap
Arrow.new { |x,y| [ y, x ] }
end
def self.left(&fun)
Arrow.new { |x| x.is_a?(Left) ? Left.new(fun[x.obj]) : x }
end
def [](*xs)
@fun[*xs]
end
def >>(other)
Arrow.new { |*x| other[self[*x]] }
end
def <<(other)
Arrow.new { |*x| self[other[*x]] }
end
def first
Arrow.new { |x,y| [ self[x], y ] }
end
def second
Arrow.swap >> first >> Arrow.swap
end
def split(other)
Arrow.new { |x,y| [ self[x], other[y] ] }
end
def fanout(other)
Arrow.new { |x| [ self[x], other[x] ] }
end
end
## Usage examples
puts
puts "Simple usage examples:"
puts
a1 = Arrow.new { |x| x*2 }
a2 = Arrow.new { |x| x-3 }
a3 = a1 >> a2
a4 = a1 << a2
p a3[4]
p a4[4]
double = a1.first
p double[5, 3]
double = a1.second
p double[5, 3]
double = a1.split(a2)
p double[5, 7]
double = a1.fanout(a2)
p double[5]
## Complexer usage example
puts
puts "Complexer usage example:"
puts
square = Arrow.new { |x| x.map { |i| i** 2 } }
remove_odd = Arrow.new { |x| x.select { |i| i % 2 == 0 } }
sum = Arrow.new { |x| x.inject { |m,i| m+i } }
arrow = remove_odd >> square >> sum
puts "Sum of squares of even numbers from 1 to 5: #{arrow[(1..5).to_a]}"
## FizzBuzz
puts
puts "FizzBuzz:"
puts
replace_fizzbuzz = Arrow.new { |x| x.is_a?(Numeric) && x % 15 == 0 ? 'fizzbuzz' : x }
replace_fizz = Arrow.new { |x| x.is_a?(Numeric) && x % 3 == 0 ? 'fizz' : x }
replace_buzz = Arrow.new { |x| x.is_a?(Numeric) && x % 5 == 0 ? 'buzz' : x }
program = replace_fizzbuzz >> replace_fizz >> replace_buzz
puts (1..100).map { |i| program[i] }.join(' ')
## Left/Right
p Arrow.left { |x| x+1 }[Arrow::Left.new(1)]
p Arrow.left { |x| x+1 }[Arrow::Right.new(1)]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment