ML:非详尽匹配

时间:2018-11-01 03:29:15

标签: sml ml non-exhaustive-patterns

我想创建名为headcol的函数,其功能类似于:

headcol[[1,2],[3,4]] = [1,3]; 

所以我做了这样的功能:

fun headcol [] = [] 
  | headcol [x::xs',y::ys'] = [x,y]

但是当我叫它时,我得到的比赛并不详尽。

2 个答案:

答案 0 :(得分:1)

IIUC,headcol将提取参数中类型为'a-list-list的列表的所有标题。您算术运算仅是[][x::xs', y::ys'],没有别的。因此,如果您的参数具有两个以上的子列表,则执行将引发:

- headcol[[1,2],[3,4], [4, 5, 9]]; 

uncaught exception Match [nonexhaustive match failure]
  raised at: a.sml:9.34
- 

如果只想处理两个元素的列表,则配对是一个更好的选择。否则,您应该匹配更多情况:

fun headcol list =
    case list of
        [] => []
      | x::xs' =>
        case x of
            [] => headcol xs'
         |  h::t => h::(headcol xs')

输出:

- headcol[[1,2],[3,4], [4, 5, 9]]; 
- val it = [1,3,4] : int list

答案 1 :(得分:1)

正如陈力指出的那样,很难回答仅由函数名称及其尝试的解决方案定义的问题。不过,head听起来像您要占据每个子列表的第一个元素,而col听起来像您要将这个列表作为矩阵对待,并且列与子视图正交。列表。

递归解决方案也可能类似于:

fun headcol [] = []
  | headcol ((x::_)::xss) = x :: headcol xss
  | headcol ([]::xss) = headcol xss

以下是使用内置高阶列表组合器的方法:

fun headcol xss =
    List.concat (List.map (fn xs => List.take (xs, 1)) xss)

我不简单做的原因:

fun headcol xss =
    List.map hd xss

是因为hd是部分函数,​​所以hd []将在运行时崩溃。

另一方面,List.take ([], 1)将返回[]

然后List.concat会将临时结果[[1],[2],[3]]合并到[1,2,3]中。

或者,如果缺少一列,请[[1],[],[3]]放入[1,3]

测试用例:

val test_headcol_0 = headcol [] = []
val test_headcol_1 = headcol [[1]] = [1]
val test_headcol_2 = headcol [[1,2],[3,4]] = [1,3]
val test_headcol_3 = headcol [[1,2,3],[4,5,6],[7,8,9]] = [1,4,7]
val test_headcol_4 = headcol [[1],[2,3],[4,5,6]] = [1,2,4]
val test_headcol_5 = headcol [[1],[],[2,3]] = [1,2]

当然,我不知道您是否期望headcol来处理没有头列的不规则矩阵。这是您不需讨论的特殊情况。在函数式编程中,通常将错误处理嵌入返回值中,而不是引发异常。

因此,例如,您可能希望从headcol返回一个'a list option,其中SOME [1,4,7]建议每一行的确有一个head列,而NONE建议至少一行未能产生一列。

或者您可以使用'a list list以外的其他数据类型来表示不允许出现缺少列的行的矩阵,例如Array2