简短:我有一个解决我的问题的方法,但它看起来有点过分,所以我想知道我是否错过了什么.
Long:我有一个2数据类型,一个Animal类型和一个Owner类型.两者都具有相同的"属性"年龄和名称.为了简单起见,我希望能够在动物和所有者上无所谓地称呼年龄和名字
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]
Run Code Online (Sandbox Code Playgroud)
这不编译,
Multiple declarations of `age'
Run Code Online (Sandbox Code Playgroud)
同样的事情对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]
Run Code Online (Sandbox Code Playgroud)
这种方法几乎与Java中的Interface的使用相同.第一个不起作用的是更接近旧的C结构方法.
是否有更快的方法来实现相同的结果?
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]
Run Code Online (Sandbox Code Playgroud)