【问题标题】:f# custom linked list and referencesf# 自定义链表和引用
【发布时间】:2014-09-13 09:06:20
【问题描述】:

我是这种语言的新手。为了尝试理解引用,我尝试以大学新生计算机科学的方式实现一个简单的定向列表。

type item = { 
    value:float 
    next:ref<item>
}

type list() = 
    let head:ref<item> = null // tried instantiation so many different ways and it likes none of em

    let sum i = 
        if i == null then
            0
        else 
            i.value + sum i.next // constructor not defined?

请告诉我为什么我不擅长这个

【问题讨论】:

  • 我会制作 refoption,这可能会满足您的要求。

标签: list recursion f# ref


【解决方案1】:

首先,您尝试以某种命令式的方式实现它 - 这没关系,但不是真正实用。 无论如何,您遇到的第一件事是,您不能分配 null - 如果您真的想要,您必须将 [&lt;AllowNullLiteral&gt;] 添加到您的 item 类型(但当然您必须将其设为类而不是记录):

[<AllowNullLiteral>]
type Item(value, next) = 
    member this.value = value
    member this.next : Item ref = next

let head : ref<Item> = ref null

let rec sum (i : Item) = 
    if i = null then
        0.0
    else 
        i.value + sum !i.next

但这几乎不是一个好主意,所以我会这样开始:

module List =

   type Item = { value : float; next : List }
   and  List = Item option ref

   let empty : List = ref None
   let single x = { value = x; next = ref None }

   // this is how you can change the list
   let rec append x l =
      let item = single x
      match !l with
      | None -> 
         l := Some item
      | Some node ->
         append x node.next

   let rec sum (l : List) =
      match !l with
      | None      -> 0.0
      | Some item -> item.value + sum item.next

现在,如果您仔细观察,您会发现,如果您只是在前面附加,那么您实际上并不需要 refs,瞧……您得到了通常的功能列表;)

PS:你也忘记了一些其他的事情:

  • 你在那里使用浮点数所以你必须使用0.0而不是0
  • 您的sum-函数必须是递归的(请注意,它不是尾递归的,因此您会遇到大列表的问题!)
  • 你必须取消引用 ref-cells 和!
  • 你必须用ref构造ref-cells(例如ref null
  • 您的 type list() = 对我来说毫无意义,所以我将其转换为模块

PPS:请不要说它不是 F#-Way 来改变这样的东西 - 这只是为了向你展示如何做到这一点......但如果你没有,就不要这样做到

【讨论】:

  • 感谢您的回答,但正如问题中所述,我实现了这样的代码以掌握引用和实例化。要么我只是不理解你的代码,要么它并没有真正回答我所追求的?对不起,你把代码改了这么多,现在对我来说有点像拉丁语^^
  • 问题到底出在哪里?我更改了第一个代码片段只是为了让您编译代码 - 例如,您不能将 Item 实现为记录,因为 F# 将不允许 null-literal 用于那些(好吧,我将类名大写太 - types 应该是大写 ;) )
  • 第二个只是null-problem(使用选项)的典型解决方案,我使这些类型更具可读性和更清晰 - 只要问你不明白的地方,我会解释
  • 这是一个很好的答案,但我不明白你为什么使用'ref'而不是'option'。你能解释一下这一点吗?
  • @FoggyFinder 因为我想与问题保持密切联系,并且在命令式(可变)链接列表中,您通常希望不时更改指向下一个列表元素的指针(正如我所说的那样这里真的很有必要)-ref cell 允许这样做(它是可变的,你可以用listItem.next := Some otherNode 重置它
猜你喜欢
  • 2019-12-23
  • 1970-01-01
  • 1970-01-01
  • 2021-03-30
  • 1970-01-01
  • 1970-01-01
  • 2011-09-24
  • 1970-01-01
  • 2013-10-16
相关资源
最近更新 更多