我有一种名为Animal的类型,其中包括动物的家族和动物的颜色。
type Animal family = [(family, color)]
data Family = Ape | Bear | Bird | Cat | Dog | Chicken
data Color = Brown | Black | White | Other
我还有一个功能,我试图访问动物的家庭和颜色。我要问的只是如何从函数中访问这些元素。例如,在大多数面向对象的语言中,我们将使用 animal.family 之类的东西访问这些元素。
animalFunction :: Animal -> String
animalFunction animal
| animal.family == Ape = "This animal is an ape."
答案 0 :(得分:7)
type Animal family = [(family, color)]
首先,这不应该编译;如果改为[(family, Color)]
这是一个类型别名,声明Animal
表示(参数化族类型,颜色)的元组列表 1 ,这很可能不是你想要什么。
正如@rightfold建议的那样,你可能想要
data Animal = Animal Family Color
或者,使用记录语法:
data Animal = Animal { family :: Family, color :: Color }
然后,你的功能:
-- record version
animalFunction :: Animal -> String
animalFunction animal
| family animal == Ape = "This animal is an ape."
| ...
注意:
family :: Animal -> Family
或者你可以模式匹配 2 。
animalFunction (Animal f c)
| f == Ape = ...
甚至:
animalFunction (Animal Ape _) = ...
但是,您可能正在寻找的是Show
,作为将某些内容转换为String
3 的一般惯用方法。
data Family = Ape | Bear | Bird | Cat | Dog | Chicken deriving (Show)
instance Show Animal where
show (Animal f _) = "This animal is an " ++ (show f) ++ "."
1 对。
2 它适用于记录和非记录,因为记录只为每个成员真正引入了Record -> Member
类型的getter,并且它们不会修改结构
3 在其他语言中,您可以将此视为为您的类实现“ToString”接口。这是一个过于简单化,但足以理解这个例子。
答案 1 :(得分:2)
要测试代数数据类型的情况,你应该使用模式匹配而不是if语句或守卫:
case myFamily of
Ape -> "This is an ape"
Bear -> "Dangerous carnivore!"
Bird -> "This can fly"
-- and so on...