【问题标题】:Additional case for a recursive data type递归数据类型的附加案例
【发布时间】:2020-09-17 17:10:53
【问题描述】:

我目前正在学习 Haskell,我想为货币 Dollar(只是钞票,而不是硬币)定义我自己的递归数据类型。

我的尝试如下所示:

data Dollar = One Dollar
             | Two Dollar
             | Five Dollar
             | Ten Dollar
             | Twenty Dollar
             | Fifty Dollar
             | Hundred Dollar

我把这个给我的一个朋友看,他说看起来不错,但他还告诉我在定义的末尾加上一个| End。他试图解释为什么这是必要的,但我无法理解他的思路。也许这里有人有我可以遵循的解释。我真的很感激。

【问题讨论】:

  • 这首先不需要递归;您所有的单参数数据构造函数都应该是空构造函数。
  • 有趣且不同寻常的定义。可能符合 corecursive 数据类型...通常的定义是例如data Dollar = One | Two | Twenty.

标签: haskell recursion types algebraic-data-types custom-data-type


【解决方案1】:

您的朋友可能表示,在某些时候,您需要一个基本案例。给定定义

data Dollar = One Dollar
            | Two Dollar
            | Five Dollar
            | Ten Dollar
            | Twenty Dollar
            | Fifty Dollar
            | Hundred Dollar
            | End

您可以将任意数量的钱表示为Dollar 值的链接列表,每个值代表一个单张账单和钱的“其余部分”。 End 将终止该列表。例如,

fortyTwoDollars :: Dollar
fortyTwoDollars = Twenty (Ten (Five (Five (Two End))))

但是,我认为没有理由将列表混入其中;单个Dollar 值可以单独表示账单,您可以使用[Dollar] 值表示集合。

data Dollar = One
            | Two
            | Five
            | Ten
            | Twenty
            | Fifty
            | Hundred
            
fortyTwoDollars :: [Dollar]
fortyTwoDollars = [Twenty, Ten, Five, Five, Two]

【讨论】:

    【解决方案2】:

    这不需要递归

    描述账单的问题不需要递归类型。让我们从一个列表开始,然后谈谈你的“美元”。

    列表

    您的账单基本上是特殊清单,具有更多构造函数且没有终止。例如,一个普通的列表是这样的:

    data List a = SomeElement a List | End
    

    这意味着我们可以构造一个链表,例如:

    myList = SomeElement 1 (SomeElement 2 ( End ) )
    

    但如果我们没有End,我们就无法停止该列表。它必须永远是SomeElement

    otherList = SomeElement 1 (SomeElement 2 ( ... oh no, I have to keep going! ...))
    

    回到“美元”

    所以你有这张特殊的美元清单。而不是用SomeElement 1 换一美元,SomeElement 5 换五美元钞票,而是OneFive。这使您可以构建一个“堆栈”账单:

    myMoney = One (Two (Five ( One ...
    

    但是你不能停下来,除非你让列表循环,比如让...成为myMoney,从而得到一个无限的One Two Five One One Two Five One One ...列表。

    质疑设计

    你可能只想要一些简单的东西:

    data Dollar = One | Two | Five
    

    然后您可以使用普通列表(例如[One, Two, Five, One])制作美元列表(键入[Dollar])。通过声明 One 账单还包含另一美元(这就是 Dollar = One Dollar 的意思),您创建的不是单个账单,而是它们的列表,这似乎没有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-20
      • 1970-01-01
      • 1970-01-01
      • 2015-03-16
      相关资源
      最近更新 更多