Skip to content

Instantly share code, notes, and snippets.

@jdewind
Created December 2, 2012 05:12
Show Gist options
  • Save jdewind/4187046 to your computer and use it in GitHub Desktop.
Save jdewind/4187046 to your computer and use it in GitHub Desktop.
Hask List Comprehension: Adaptation of Triangle Example in Tutorial
module Main where
import System.Environment
type Triangle = (Int, Int, Int)
perimeter :: Triangle -> Int
perimeter (a, b, c) = a + b + c
rightTriangle :: Triangle -> Bool
rightTriangle (a, b, c) = a^2 + b^2 == c^2
rightTriangles :: [Triangle] -> [Triangle]
rightTriangles xs = [ x | x <- xs, rightTriangle x]
withMultipleOf :: [Triangle] -> Int -> [Triangle]
withMultipleOf xs m = [x | x <- xs, mod (perimeter x) m == 0]
generateTriangles :: Int -> [Triangle]
generateTriangles num = [ (a, b, c) | c <- [1..num], b <- [1..num], a <- [1..num] ]
printResults :: [String] -> IO ()
printResults [num, per] = do
print (withMultipleOf (rightTriangles (generateTriangles (read num))) (read per))
printResults args = putStrLn "Wrong number of arguments"
main :: IO ()
main = do
args <- getArgs
printResults args
require 'pp'
class Triangle
attr_accessor :a, :b, :c
def initialize(a, b, c)
@a, @b, @c = a, b, c
end
def right_triangle?
@a**2 + @b**2 == @c**2
end
def perimeter
@a + @b + @c
end
def self.only_right_triangles(triangles)
triangles.select { |x| x.right_triangle? }
end
def self.right_and_with_perimeter_multiple_of(triangles, multiple)
only_right_triangles(triangles).select { |x| x.perimeter % multiple == 0 }
end
def self.generate(num)
triangles = []
range = (1..num).to_a
range = range.product range, range
range.map { |(a,b,c)| Triangle.new a, b, c }
end
def inspect
"(#{@a}, #{@b}, #{@c})"
end
end
if __FILE__ == $0
if ARGV.count == 2
triangles = Triangle.generate ARGV[0].to_i
pp Triangle.right_and_with_perimeter_multiple_of triangles, ARGV[1].to_i
else
puts "Wrong number of arguments"
end
end
@jdewind
Copy link
Author

jdewind commented Dec 2, 2012

time ./triangle 200 10

real    0m8.123s
user    0m8.070s
sys 0m0.051s

time ruby triangle.rb 200 10

real    0m7.474s
user    0m7.006s
sys 0m0.356s

@jdewind
Copy link
Author

jdewind commented Dec 2, 2012

  • Ruby implementation is far less safe due to its dynamic nature
    • It is impossible to pass the wrong type to the Haskell implementation
    • Haskell's read infers the type passed to the functions
    • Tuples are types in themselves and Haskell has a nice way of making synonymous types
  • Pattern matching in Haskell made handling arguments more elegant
  • Ruby appears to be faster in this one particular case
  • List comprehension in Haskell is really nice
  • I like how both implementations read

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment