【发布时间】:2014-07-09 14:20:43
【问题描述】:
在http://www.haskell.org/pipermail/haskell-cafe/2007-August/030096.html 中,类型类方法collide 被定义为将2 元组作为其单个参数,而不是两个“正常”参数(我想我理解部分应用等)。
{-# 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"
这样做的目的是什么?
什么时候使用元组参数而不是多个参数更好?
【问题讨论】:
-
我的意见是当两个值有内在联系时应该使用元组,例如表示坐标
(x, y)的元组。幸运的是,对于 2 元组,我们有curry和uncurry来在这些表示之间进行转换,以便在其中一个比另一个更方便时进行转换。 -
元组的另一个重要用途是当您不想创建自定义数据类型,但仍希望使用同义词来保持类型签名清晰:
type 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?" -
@chrisdew 这取决于问题的类型。正如 bhekilir 建议的那样,如果值是连接的,则使用元组。大多数时候我不使用元组。如果它们本质上是连接的,我会将元组结构变成一个记录。柯里化可以更容易地重用,所以我通常会坚持这一点。
-
@chrisdew 在您的示例中,我个人会选择将参数分隔到
collide,因为您不太可能与同一个对象发生多次冲突,例如data Meteor = Meteor; instance Collide Planet Meteor where ...和meteorStorm :: [Meteor] -> [String]; meteorStorm = map (flip collide Planet),而如果您使用元组,则必须编写meteorStorm = map (\m -> collide (m, Planet)。虽然字符数量大致相同,但我个人认为前者更具可读性。
标签: haskell tuples typeclass multimethod