了解指定数据类型的尾递归

问题描述

因此,我对递归的理解比较好,但是在F#中,它具有创建自己的数据类型集的能力,所以我不理解如何编写函数来引用该特定方案。谢谢您的帮助

type 'element mylist = PEANUT | BUTTER of 'element * 'element mylist
let exampleList = BUTTER (1,BUTTER (2,BUTTER (3,PEANUT)))

试图编写一个尾部递归函数来反转此列表吗?

这是我传统上的写法

let rec helper a b =
      match a with
        | [] -> b
        | h::t -> helper t (h::b)

    let rev L = helper L []

在这是我一直在尝试的事情:

let rec tailrevMylist a L =
      match a with
      | [] -> []
      | PEANUT::t -> tailrevMylist t (BUTTER::L)
 

    let revMylist L =
      tailrevMylist  L []

***开始更新/更改***

let rec tailrevMylist a b =
      match a with
      | PEANUT -> b
      | h::t -> tailrevMylist BUTTER (a,b)
 

    let revMylist L =
      tailrevMylist  L []

仍然得到不正确的类型-尝试使用CONS代替h,但是由于期望联合而无法使用。 ***结束更新***

但是,当我尝试运行revMylist exmapleList时,由于该函数期望'a mylist list但在测试中键入了int mylist,因此出现错误。我需要获得一个期望int mylist函数

***解决方案***

let rec tailrevMyList a b  =
      match a with
        | PEANUT -> b
        | BUTTER (head,tail) -> (tailrevMyList tail (BUTTER (head,b)))
 

    let revMylist L = tailrevMyList L PEANUT

解决方法

列表的定义本质上是:

type 'a list = [] | :: of 'a * 'a list
您可能会注意到的

mylist的定义非常相似。唯一的区别是使用[]代替PEANUT::代替BUTTER,而::也是中缀运算符。

您可能还会注意到,这意味着您将以毫无意义的方式混合使用listmylist构造函数。因此,除了尝试解决当前的实现方式,我只会告诉您如何通过应用一些非常简单的规则来机械地将helper函数转换为使用mylist

  1. []替换为PEANUT
  2. a :: b替换为BUTTER (a,b)

这就是全部。因此,我不只是给您答案,而是让您使用这些规则自己得出答案。祝你好运!