访问 Haskell 中自定义类型变量的元素?

Accessing elements of custom type variables in Haskell?

我有一个名为 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."
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."
    | ...

Note: family :: Animal -> Family

或者你可以只进行模式匹配2.

animalFunction (Animal f c)
    | f == Ape = ...

甚至:

animalFunction (Animal Ape _) = ...

但是,您可能正在寻找的是 Show,作为将某些内容转换为 String3.[= 的通用惯用方法24=]

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 在其他语言中,您可以认为这是为您的 class 实现 "ToString" 接口。过于简单化了,但足以理解这个例子。

要测试代数数据类型的情况,您应该使用模式匹配而不是 if 语句或守卫:

case myFamily of
  Ape -> "This is an ape"
  Bear -> "Dangerous carnivore!"
  Bird -> "This can fly"
  -- and so on...