【问题标题】:Understanding Recursive Algebraic Types in Functional Programming了解函数式编程中的递归代数类型
【发布时间】:2012-03-31 21:34:26
【问题描述】:

嘿,我在理解递归代数类型的工作原理以及如何准确使用它们时遇到了一些麻烦。例如,对自然数采用以下 RAT 定义:

data Nat = Zero | Succ Nat 

我们在这里使用 RAT 是因为值的集合需要是无限的,而且我知道原则是用前一个值来表达每个新值,但我不明白这是如何形成自然数的。有人介意清理一下吗?谢谢

【问题讨论】:

  • 用1 + 翻译Succ。每个自然数都是1 + (1 + ( ... (1 + 0) ... )),用于适当数量的操作。

标签: haskell recursion functional-programming


【解决方案1】:

这表明:

  • Nat 是一种类型。

  • Zero 的类型为 Nat。这表示自然数 0。

  • 如果n 的类型为Nat,则Succ n 的类型为Nat。这表示自然数n+1。

例如,Succ (Succ Zero) 代表 2,Succ (Succ (Succ Zero)) 代表 3,Succ (Succ (Succ (Succ Zero))) 代表 4,以此类推。 (这种定义从 0 到后继的自然数的系统称为Peano axioms。)

事实上,Zero 和Succ 只是声明创建Nat 值的特殊类型的函数(构造函数):

Zero :: Nat
Succ :: Nat -> Nat

与常规函数的不同之处在于您可以通过模式匹配将它们分开:

predecessor :: Nat -> Nat
predecessor Zero = Zero
predecessor (Succ n) = n

这对递归代数数据类型没有什么特别之处,当然,只是代数数据类型;但一个简单的事实是,代数数据类型可以具有与其字段之一相同类型的值,这就是在这里创建递归的原因。

【讨论】:

  • 感谢 ehird 这么清晰的回答!那么 Succ 构造函数是代表 n+1 的内置函数吗?我很困惑,因为我认为它只是以正常方式声明另一个可能的值。如果我们有一个数 n,为什么我们要表示值 n+1,即自然数序列中的下一个值?我们不只是关心如何表达值 n 吗?感谢最后的模式匹配位 - 它非常有用!
  • 不,它不是内置的;您可以将其重命名为 Fnarf 并且完全相同。我们的想法是我们定义这种类型,并为它的每个值分配一个自然数的含义:我们用该类型表示数据。 Succ n 表示 n + 1,因为 n 已经必须由 another Nat 表示。如果你有Zero(0),你想要1,你必须使用Succ Zero,来表示0 + 1 = 1。如果你有Succ Zero(1),你想要2,你必须使用Succ (Succ Zero),表示 1 + 1 = 2... 以此类推。
  • @user1058210 不,Succ 不是内置的。这只是您给构造函数的名称。您需要一种从n 到n+1 的方法,因此您可以表示任何数字。如果定义只是data Nat = Zero,则只能表示零。当然,您可以将其扩展到更多的数字,例如 data Nat = Zero | One | Two,但这种方法只能为您提供有限数量的数字。使用 Succ,您只需将 Succ 应用于 Zero n 次即可代表数字 n。
  • 好的,我想我明白了!谢谢大家的帮助!
猜你喜欢
  • 2016-04-09
  • 1970-01-01
  • 2022-06-16
  • 2021-03-22
  • 1970-01-01
  • 2020-05-14
  • 2016-08-20
  • 2015-11-13
相关资源
最近更新 更多