ML :匹配非穷尽
ML : match non-exhaustive
我想创建名为 headcol
的函数,其工作方式如下:
headcol[[1,2],[3,4]] = [1,3];
所以我做了这样的功能:
fun headcol [] = []
| headcol [x::xs',y::ys'] = [x,y]
但是当我调用它时,我得到了一个非穷尽的匹配项。
IIUC,headcol
会提取参数中的所有列表头,类型为'a-list-list
。你 mathc 只是 []
和 [x::xs', y::ys']
,没有其他任何东西。所以,如果你的论点有 2 个以上的子列表,execption 将引发:
- headcol[[1,2],[3,4], [4, 5, 9]];
uncaught exception Match [nonexhaustive match failure]
raised at: a.sml:9.34
-
如果你只想处理两个元素的列表,pair 是更好的选择。否则,你应该匹配更多的案例:
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
正如陈力指出的那样,很难回答仅由函数名称及其尝试解决方案定义的问题。尽管如此,head
听起来您想要获取每个 sub-list 的第一个元素,而 col
听起来您正在将这个列表列表视为一个矩阵,其中的列与sub-lists.
递归解决方案也可能如下所示:
fun headcol [] = []
| headcol ((x::_)::xss) = x :: headcol xss
| headcol ([]::xss) = headcol xss
以下是使用 built-in higher-order 列表组合器的方法:
fun headcol xss =
List.concat (List.map (fn xs => List.take (xs, 1)) xss)
我不简单做的原因:
fun headcol xss =
List.map hd xss
是因为hd
是偏函数,所以hd []
会在run-time处崩溃。
另一方面,List.take ([], 1)
将 return []
。
和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
的行为。这是一个你不会进入的极端案例。在函数式编程中,您经常将错误处理嵌入到 return 值中而不是抛出异常。
因此,例如,您可能想要从 headcol
到 return 一个 'a list option
,其中 SOME [1,4,7]
表明每一行都有一个标题列,并且 NONE
表明至少有一行未能生成一列。
或者您可以使用 'a list list
以外的数据类型来表示不允许行缺少列的矩阵,例如一个 Array2.
我想创建名为 headcol
的函数,其工作方式如下:
headcol[[1,2],[3,4]] = [1,3];
所以我做了这样的功能:
fun headcol [] = []
| headcol [x::xs',y::ys'] = [x,y]
但是当我调用它时,我得到了一个非穷尽的匹配项。
IIUC,headcol
会提取参数中的所有列表头,类型为'a-list-list
。你 mathc 只是 []
和 [x::xs', y::ys']
,没有其他任何东西。所以,如果你的论点有 2 个以上的子列表,execption 将引发:
- headcol[[1,2],[3,4], [4, 5, 9]];
uncaught exception Match [nonexhaustive match failure]
raised at: a.sml:9.34
-
如果你只想处理两个元素的列表,pair 是更好的选择。否则,你应该匹配更多的案例:
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
正如陈力指出的那样,很难回答仅由函数名称及其尝试解决方案定义的问题。尽管如此,head
听起来您想要获取每个 sub-list 的第一个元素,而 col
听起来您正在将这个列表列表视为一个矩阵,其中的列与sub-lists.
递归解决方案也可能如下所示:
fun headcol [] = []
| headcol ((x::_)::xss) = x :: headcol xss
| headcol ([]::xss) = headcol xss
以下是使用 built-in higher-order 列表组合器的方法:
fun headcol xss =
List.concat (List.map (fn xs => List.take (xs, 1)) xss)
我不简单做的原因:
fun headcol xss =
List.map hd xss
是因为hd
是偏函数,所以hd []
会在run-time处崩溃。
另一方面,List.take ([], 1)
将 return []
。
和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
的行为。这是一个你不会进入的极端案例。在函数式编程中,您经常将错误处理嵌入到 return 值中而不是抛出异常。
因此,例如,您可能想要从 headcol
到 return 一个 'a list option
,其中 SOME [1,4,7]
表明每一行都有一个标题列,并且 NONE
表明至少有一行未能生成一列。
或者您可以使用 'a list list
以外的数据类型来表示不允许行缺少列的矩阵,例如一个 Array2.