展平SML上的数据类型列表获取问题

展平SML上的数据类型列表获取问题,sml,flatten,Sml,Flatten,我有一个关于家庭作业的问题,问题是 使用的数据类型如下: datatype 'a llist = LList of 'a llist list| Elem of 'a; 嵌套列表由多态类型的元素或嵌套列表列表组成。这个 以下是一些例子: Elem(1); LList []; LList([Elem(1), LList([Elem(2), LList([Elem 1, Elem(3)]), Elem(4)])]); 编写一个函数flant,该函数接受嵌套列表作为输入并返回 一份简单的清单 嵌套

我有一个关于家庭作业的问题,问题是

使用的数据类型如下:

datatype 'a llist = LList of 'a llist list| Elem of 'a;
嵌套列表由多态类型的元素或嵌套列表列表组成。这个 以下是一些例子:

Elem(1);
LList [];
LList([Elem(1), LList([Elem(2), LList([Elem 1, Elem(3)]), Elem(4)])]);
编写一个函数flant,该函数接受嵌套列表作为输入并返回 一份简单的清单 嵌套列表中的元素。请注意,结果列表中的元素顺序相同 如嵌套列表中所示

但我的密码是

fun flatten Elem x = [x] | LList x = (List.concat (map (fn a => flatten(a)) x));
有问题

- fun flatten Elem x = [x] | LList x = (List.concat (map (fn a => flatten(a)) x));
stdIn:13.1-17.71 Error: clauses do not all have same function name

stdIn:13.1-17.71 Error: clauses do not all have same number of patterns

stdIn:17.4-17.8 Error: data constructor Elem used without argument in pattern

stdIn:13.1-17.71 Error: types of rules do not agree [tycon mismatch]
  earlier rule(s): 'Z * 'Y -> 'Y list
  this rule: 'X list -> 'W list
  in rule:
    x => List.concat ((map (fn a => flatten a)) x)

stdIn:13.1-17.71 Error: right-hand-side of clause does not agree with function result type [tycon mismatch]
  expression:  'Z -> 'Z list
  result type:  'Y list
  in declaration:
    flatten =
      (fn arg =>
            (fn arg =>
                  (case (arg,arg)
                  of (_,x) => x :: nil
                   | x => List.concat ((map <exp>) x))))
-fun flatten Elem x=[x]| LList x=(List.concat(map(fn a=>flatten(a))x));
stdIn:13.1-17.71错误:子句不都具有相同的函数名
stdIn:13.1-17.71错误:子句的模式数不尽相同
stdIn:17.4-17.8错误:在模式中使用的数据构造函数元素没有参数
stdIn:13.1-17.71错误:规则类型不一致[tycon不匹配]
早期规则:“Z*”Y->“Y列表
此规则:“X列表->”W列表
按照规则:
x=>List.concat((映射(fn a=>flatte a))x)
stdIn:13.1-17.71错误:条款右侧与功能结果类型不一致[tycon不匹配]
表达式:“Z->”Z列表
结果类型:“Y列表”
在声明中:
压扁=
(fn arg=>
(fn arg=>
(案例(arg,arg)
of(ux)=>x::nil
|x=>List.concat((map)x)))

我不知道我的代码有什么问题。

您的代码中有一些语法问题

否则,逻辑是正确的

以下是更正的版本:

fun flatten(元素x)=[x]
|展平(LList x)=(List.concat(map(fn a=>展平(a))x));

由于quoify提供了一个完整的解决方案,下面是一个使用显式递归而非库函数的解决方案,以及quoify的concat map解决方案的精简版本:

fun flatten (Elem x) = [x]
  | flatten (LList []) = []
  | flatten (LList (LL::LLs)) = flatten LL @ flatten (LList LLs)
这里,
LL
是作为第一个子分支的“ALLIST”,而
LLs
是作为剩余子分支的“ALLIST”列表。llist的类型名可能会有点混淆,因为当它是一个树时,它类似于一个列表。因此,您可以将
LL
视为一棵树,将
LLs
视为一列树

基本方法是对具有一个元素的树、具有零分支的树以及具有一个或多个分支的树进行模式匹配。将此转换为使用列表组合符(如
map
concat
)的解决方案,您可以确定递归方案:与其将递归拆分为“空”/“非空”模式,不如将整个递归任务交给
map

(* BROKEN *)
fun flatten (Elem x) = [x]
  | flatten (LList ts) = map flatten ts
编译器给我们的问题是:

! Toplevel input:
!   | flatten (LList ts) = map flatten ts;
!                          ^^^^^^^^^^^^^^
! Type clash: expression of type
!   'a list list
! cannot have type
!   'a list
! because of circularity
因此,既然
flatte
返回一个“a列表”,那么
map flatte
就必须返回一个“a列表”,因为它需要多个树并为每个树生成一个展平列表。但是“a列表”与“a列表”非常接近,我们可以使用
list.concat将内部列表合并成一个大列表:

fun flatten (Elem x) = [x]
  | flatten (LList ts) = List.concat (List.map flatten ts)
您还可以为此特定组合创建帮助器函数:

fun concatMap f = List.concat o List.map f
fun flatten (Elem x) = [x]
  | flatten (LList ts) = concatMap flatten ts
fun concatMap f = List.concat o List.map f
fun flatten (Elem x) = [x]
  | flatten (LList ts) = concatMap flatten ts