几个数据类型与Type构造函数接受相同的Type,如何获取同名的访问器?

时间:2017-11-07 14:57:32

标签: haskell

简短:我有一个解决我的问题的方法,但它似乎有点矫枉过正,所以我想知道我是否错过了什么。

长: 我有一个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结构方法。

有更快的方法来达到相同的效果吗?

1 个答案:

答案 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]