简短:我有一个解决我的问题的方法,但它似乎有点矫枉过正,所以我想知道我是否错过了什么。
长: 我有一个2数据类型,一个动物类型和一个所有者类型。两者都具有相同的属性"年龄和名字。为了简单起见,我希望能够在动物和所有者
上无差别地称呼年龄和名字type Age = Int
type Name = String
data AnimalType = Dog | Cat | Snake
deriving (Read, Show,Eq)
--with datatype and pattern matching
data Animal = Animal AnimalType Name Age
deriving(Show, Eq)
name (Animal _ name _) = name
age (Animal _ _ age) = age
animalType (Animal animalType _ _) = animalType
data Owner = Owner Name Age [Animal]
deriving(Show,Eq)
name (Owner name _ _) = name
age (Owner _ age _) = age
animals (Owner _ _ animals) = animals
garfield = Animal Cat "Garfield" 8
rantanplan = Animal Dog "Rantanplan " 4
kaa = Animal Snake "Kaa" 15
dupond = Owner "Dupont" 28 [garfield, rantanplan]
bob = Owner "Bob" 35 [kaa]
这不编译,
Multiple declarations of `age'
同样的事情对Record语法也不起作用。
这样做,一个人被迫为所有者命名不同的年龄和动物的年龄。
然后我挖了一下,发现我可以使用类型类来实现它。
type Age = Int
type Name = String
class Nameable a where
name:: a -> Name
class Ageable a where
age:: a -> Age
data AnimalType = Dog | Cat | Snake
deriving (Read, Show,Eq)
--with datatype and pattern matching
data Animal = Animal AnimalType Name Age
deriving(Show, Eq)
instance Nameable Animal where
name (Animal _ name _) = name
instance Ageable Animal where
age (Animal _ _ age) = age
animalType (Animal animalType _ _) = animalType
data Owner = Owner Name Age [Animal]
deriving(Show,Eq)
instance Nameable Owner where
name (Owner name _ _) = name
instance Ageable Owner where
age (Owner _ age _) = age
animals (Owner _ _ animals) = animals
garfield = Animal Cat "Garfield" 8
rantanplan = Animal Dog "Rantanplan " 4
kaa = Animal Snake "Kaa" 15
dupond = Owner "Dupont" 28 [garfield, rantanplan]
bob = Owner "Bob" 35 [kaa]
这种方法几乎与Java中的Interface的使用相同。第一个不起作用的是更接近旧的C结构方法。
有更快的方法来达到相同的效果吗?
答案 0 :(得分:6)
Haskell中的记录(及其访问者)是......次优的。也就是说,关于重复记录字段的这个特殊问题有DuplicateRecordFields
扩展形式的解决方法(自GHC 8.0起)。请注意,记录访问器必须以明确的方式使用(这里没有花哨的多态性)。
{-# LANGUAGE DuplicateRecordFields #-}
type Age = Int
type Name = String
data AnimalType = Dog | Cat | Snake
deriving (Read, Show, Eq)
data Animal = Animal
{ animalType :: AnimalType
, name :: Name
, age :: Age
} deriving(Show, Eq)
data Owner = Owner
{ name :: Name
, age :: Age
, animals :: [Animal]
} deriving(Show, Eq)
garfield = Animal Cat "Garfield" 8
rantanplan = Animal Dog "Rantanplan " 4
kaa = Animal Snake "Kaa" 15
dupond = Owner "Dupont" 28 [garfield, rantanplan]
bob = Owner "Bob" 35 [kaa]