【问题标题】:hierarchical data types分层数据类型
【发布时间】:2011-12-02 17:13:01
【问题描述】:

我想分层定义数据类型,比如:

data Cat = BigCat | SmallCat
data Animal = Cat | Dog

然后编写一个将 Animals 作为参数的函数,并使用这样的模式匹配编写它:

bigger::Animal -> Animal -> Bool
bigger SmallCat BigCat = False
bigger BigCat SmallCat = True
bigger Dog Cat = True
bigger Cat Dog = False

编译器抱怨。它不想将函数签名中明确写入的类型Animal 与模式匹配的第一行和第二行中的类型Cat 进行匹配。为什么 haskell 不承认大猫或小猫动物?

【问题讨论】:

  • “为什么 Haskell 不承认大猫或小猫是动物?” - 因为不是。 BigCat :: CatSmallCat :: Cat,但 Cat :: Animalconstructor Cattype Cat 无关。

标签: haskell


【解决方案1】:

你把 types 和它们的 constructors 混在一起了。类型是可以创建变量的东西。类型构造函数用于创建此类数据。在您的代码中,data Animal = Cat | Dog 用两个 构造函数 CatDog 声明了一个 type Animal。在另一行中,您定义了一个数据类型Cat。这没有问题,因为类型和构造函数不共享相同的命名空间。

如果你想在你的Animal 中嵌入一个Cat 类型的对象(如果使用了构造函数Cat),你可以在构造函数中添加一个字段:

data Animal = Cat Cat | Dog

这意味着:Animal 是一个有两个构造函数的类型,CatDogCat 有一个类型为 Cat 的字段,而Dog 没有。” em> 如果要使用构造函数Cat 创建对象,则必须将Cat 类型的对象传递给它:

myCat = Cat BigCat

如果你想匹配Animal,你必须列出匹配的构造函数的所有字段。比较代码的更正版本:

data Cat = BigCat | SmallCat
data Animal = Cat Cat | Dog

bigger :: Animal -> Animal -> Bool
bigger (Cat SmallCat) (Cat BigCat)   = False
bigger (Cat BigCat)   (Cat SmallCat) = True
bigger Dog            (Cat _)        = True
bigger (Cat _)         Dog           = False

_ 表示不关心 - 无论传递的对象如何,这将始终匹配。

【讨论】:

  • +1 用于解释适合初学者的类型和构造函数之间的区别。
【解决方案2】:

这里的直接错误是Animal 定义了两个数据构造函数,与Cat 无关:表达式Cat 的类型为Animal,而表达式BigCat 的类型为@ 987654326@.

要以简单的方式创建嵌套数据类型,您需要将 Cat 类型作为相关构造函数的参数:

data Cat = BigCat | SmallCat
data Animal = Cat Cat | Dog

然后你可以这样做:

bigger (Cat SmallCat) (Cat BigCat) = False
bigger (Cat BigCat) (Cat SmallCat) = True
bigger Dog (Cat _) = True
bigger (Cat _) Dog = False

如果超出一个简单的示例,这将变得非常笨拙,但是,Cat 类型中的冗余是痛苦的,并且标识符 Cat 的两种不同用途是不必要的混淆。一个轻微的改进是避免将大小与物种混为一谈,而是做这样的事情:

data Size = Big | Small
data Species = Cat | Dog
data Animal = Animal Species Size

这里的一个优点是您可以更轻松地扩展这两种类型,而无需添加尽可能多的样板废话。

但是,除了玩具示例之外,这两种方法都非常愚蠢,在实际使用中,很可能会有更好的方法更可取。如果类型真的是比猫狗更有意义的简单枚举,那么 deriving Ord, Enum, &c。比特殊用途的东西更可取。如果意图是以更开放的方式对具有各种属性的实体进行建模,那么值得考虑更适合实际问题的其他设计。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-11
    • 2020-07-09
    • 1970-01-01
    • 1970-01-01
    • 2011-11-03
    • 2020-12-09
    相关资源
    最近更新 更多