In http://www.haskell.org/pipermail/haskell-cafe/2007-August/030096.html the typeclass method collide
is defined as taking a 2-tuple as its single argument, rather than two "normal" arguments (I think I understand partial application, etc.).
{-# OPTIONS_GHC -fglasgow-exts
-fallow-undecidable-instances
-fallow-overlapping-instances #-}
module Collide where
class Collide a b where
collide :: (a,b) -> String
data Solid = Solid
data Asteroid = Asteroid
data Planet = Planet
data Jupiter = Jupiter
data Earth = Earth
instance Collide Asteroid Planet where
collide (Asteroid, Planet) = "an asteroid hit a planet"
instance Collide Asteroid Earth where
collide (Asteroid, Earth) = "the end of the dinos"
-- Needs overlapping and undecidable instances
instance Collide a b => Collide b a where
collide (a,b) = collide (b, a)
-- ghci output
*Collide> collide (Asteroid, Earth)
"the end of the dinos"
*Collide> collide (Earth, Asteroid)
"the end of the dinos"
What is the purpose of this?
When is it better to use a tuple argument rather than multiple arguments?
(x, y)
. Luckily for 2-tuples, we havecurry
anduncurry
to convert between these representations for whenever one is more convenient than the other. – Illusionismtype FName = String; type LName = String; type Age = Int; type Person = (FName, LName, Age); greet :: Person -> IO (); greet (fname, lname, age) = putStrLn $ if age >= 30 then "Hello, " ++ fname ++ " " ++ lname else "Sup?"
– Illusionismcollide
, since it's not unlikely that you could have multiple collisions with the same object, e.g.data Meteor = Meteor; instance Collide Planet Meteor where ...
andmeteorStorm :: [Meteor] -> [String]; meteorStorm = map (flip collide Planet)
, whereas if you use tuples you'd have to write itmeteorStorm = map (\m -> collide (m, Planet)
. While about the same number of characters, I personally think the former is more readable. – Illusionism