Recursion Ocaml:将列表排序为等价类

Recursion Ocaml:将列表排序为等价类,recursion,functional-programming,ocaml,equivalence-classes,Recursion,Functional Programming,Ocaml,Equivalence Classes,我最近开始学习ocaml,但在解决问题时遇到了困难 目标: 给定一个整数列表和一个函数,根据给定函数将整数排序为等价类,作为另一个列表中的列表。等效列表的顺序必须与原始列表中给出的顺序相同 更新:我决定尝试在没有库函数的情况下让它工作 这是到目前为止我的代码。它编译但不运行。任何语法方面的帮助都将不胜感激 let buckets f lst = let rec helpfunction f lst newlist = match lst with | [] ->

我最近开始学习ocaml,但在解决问题时遇到了困难

目标:

给定一个整数列表和一个函数,根据给定函数将整数排序为等价类,作为另一个列表中的列表。等效列表的顺序必须与原始列表中给出的顺序相同

更新:我决定尝试在没有库函数的情况下让它工作

这是到目前为止我的代码。它编译但不运行。任何语法方面的帮助都将不胜感激

let buckets f lst =
  let rec helpfunction f lst newlist = 
     match lst with
      | [] ->newlist
      | h::t -> match newlist with
             | [] -> helpfunction f lst [h]@newlist
             | [a]::_ -> if f h a 
                  then helpfunction f t [a::h]@newlist
                  else helpfunction f t ([a]::[h]@mylist

重要提示:这是一个家庭作业问题,所以我不是在寻找为我粘贴的代码。我试着在我的家里用逻辑来解释它,并在整体思维过程和语法方面提供一些帮助。一旦我开始工作,我会努力使它更有效率

好吧,让我们试着解决这个任务,而不是实际执行:)

大致来说,算法如下所示:

  • 从源列表中获取整数
    x

  • 如果列表的目标列表(每个列表都包含相同等价类的整数)包含相应等价类的列表,则将
    x
    添加到此列表中

  • 否则,创建一个包含单个值的新等价类列表(
    [x]
    ),并将其添加到目标列表中

  • 对目标列表中的其他整数重复1-3

  • (1) ,(3)和(4)似乎很难实现

    面临的挑战是如何实施(2)以及如何高效实施:)

    “目标列表包含…”的列表可以重新表述为“在目标列表中存在一个列表,如…”-这给了我们一个强烈的提示,
    list.exists
    ,可以在此处使用。测试的内容也或多或少很清楚:相同等价类列表中的每个成员在定义上都是等价的,因此我们可以只取头部,使用
    p
    将其与
    x
    进行比较

    问题是如何将整数添加到另一个列表中的列表中。列表是不可变的,所以我们不能把它放在那里。。。但是我们可以将目标列表转换,或者将其折叠到另一个列表中。我敢打赌你得到了提示:
    列表。向左折叠是另一个难题

    因此,总结所有这些,我们可以得出以下“更精确”的算法

  • 从空目标列表开始
    res

  • 从源列表
    l

  • 使用
    List.exists
    检查
    res
    中是否有列表
    lst
    ,例如其头部
    h
    p x h=true

  • 如果是,使用
    List。向左折叠
    将当前
    res
    转换为新的
    lst
    替换为
    x::lst
    ,并按原样复制所有其他等效类列表

  • 如果否,则引入一个新的等价类(将
    [x]
    添加到
    res

  • 对源列表中的下一个整数重复2-5,直到其为空


  • 实际上(几乎)遵循此算法的实现相对简单。但是它不是很有效,因为
    存在
    折叠
    将在同一个列表上迭代两次,执行完全相同的检查。通过一些调整,应该可以在一次运行中完成,但这个无效的运行应该足够好,作为起点…

    您尝试的是获取输入中的每个元素,然后将其插入列表结果列表的某个位置。让我提出一种不同的方法

    您从一个“输入列表”和一个空的“构建结果列表”开始

    如果输入为空,则结果已完成并返回


    否则,将输入拆分为head和tail(模式匹配已经这样做了)。接下来,将输入列表划分为与head等效的项和与head不等效的项。以第二个列表作为新输入,以(第一个列表::结果)作为新结果递归。

    您还没有问过特定的问题。您是否正在寻找帮助来编译代码(我看到一些错误)?或者你想知道你提出的方法是否可行吗?一点A,一点B。对我来说,第一步是让我的代码正常工作,然后我将关注在类列表上循环两次的效率。最好是一次性完成现有的工作和折叠。检查类列表是否为空(为当前项创建新类)。否则,检查head类是否等同于当前项(添加它并返回新的_class::tail)。我的想法是先从“愚蠢的”和简单的解决方案开始,用简单的语言一步一步地解释,而不需要代码。但我同意你…谢谢你的回复。我的源列表只是一个基本列表,而不是列表列表。你认为最好立即开始将列表排序为一个列表列表,每个内部列表只包含一项吗?@KonstantinStrukov我想我现在掌握了逻辑。上面新代码中的语法正确吗?“我的源代码列表只是一个基本列表,而不是列表列表”@LostinRecursion当然正确
    int list list
    将是目标列表的类型,而不是源列表的类型。抱歉,如果我不清楚-我也是OCaml新手,如果没有代码,我很难解释解决方案:)注意:您可以使用
    let helper results=function[]->results |(head::)作为输入->…
    感谢您的回复。我正试图根据你的建议实施和做出改变。我有点被困在名单的一部分。你认为嵌套匹配语句是最好的方法吗?\n我想我现在已经掌握了逻辑,尽管我正在学习高阶函数的语法。我在上面加了我的新代码。通常我