SML中的匹配警告和模式匹配

时间:2019-02-26 18:55:43

标签: sml

我想知道了解SML中的模式匹配是否会继续发出Match警告的最佳策略。

考虑以下功能:

fun f 7 (x,y) = x * 5.1 | f x (y,#"a") = y;

乍看之下,它似乎没有提供Match警告。但是,如果我运行它,它将。

从我的角度来看,我们处理所有案件。我们不处理哪种情况?即使f 7 (x,#"a")我们知道应该是哪种情况(第一个)。

我的问题是,如何确定该功能将输出该减弱的信号。

此外,我很乐意回答以下功能为何无效的问题:

fun f (x::xs) (y::ys) (z::zs) = y::xs::ys::zs;

没有zs有效。 zs如何进行更改?

1 个答案:

答案 0 :(得分:0)

  

我的问题是,如何确定该功能将输出该减弱的信号。

编译器具有确定该算法的算法。

要么使用编译器并警告您,要么在脑海中使用类似的启发式方法。

请参见Luc Maranget(2007)的Warnings for pattern matching

它涵盖了查找缺失和重复模式的问题,算法和实现。


一种有用的启发式方法:将线排列起来,例如喜欢:

fun fact 0 = 1
  | fact n = n * fact (n - 1)

并问自己:是否存在值的组合,而该函数的一种情况并不能解决?每个功能用例都应解决输入的某些特定逻辑类别。由于您的示例不是实际示例,因此无法使用此方法,因为输入中没有逻辑类别。

fact有点简单,因为非常容易确定它属于0还是n类别。

但是,值~1是否正确地属于以下类别之一?

a practical example是有问题模式的函数:

fun hammingDistance [] [] = SOME 0
  | hammingDistance (x::xs) (y::ys) =
    if length xs <> length ys then NONE else
    if x = y
      then hammingDistance xs ys
      else Option.map (fn d => d + 1) (hammingDistance xs ys)

似乎有两种逻辑情况:列表为空,或者不是:

  1. 输入列表为空,在这种情况下,第一个正文被激活。

  2. 输入列表不是空的,在这种情况下它们的长度是不同的或相等。

    1. 如果长度不同,请NONE

    2. 如果它们的长度相等,则计算距离。

当然,这是一个细微的错误,因为第一个列表可以为空,而第二个列表不为空,而第二个列表可以为空,而第一个列表不为空。如果是这种情况,则第二个主体永远不会受到撞击,而且永远不会区分不同/相等长度的物体。因为分类的任务是在模​​式匹配和 if-then-else 之间进行划分,并且优先于模式匹配。

我个人先发制人地解决此类问题的方法是这样思考:

  • 当我在列表上进行模式匹配时(例如),我必须覆盖两个构造函数(1. [],2。::),而当我在两个列表上进行模式匹配,我必须介绍其构造函数的笛卡尔积(1. [][],2。[]::,3。{{1 }},::和4。[]::)。

  • 我只能计算两个模式/实体,没有一个可以涵盖四个案例中的一个,所以我知道我缺少一些。

  • 如果有一个带有变量的案例,我必须问一下它涵盖了多少个常见案例。

    ::

    这里只有三个图案/实体,但最后一个是万能的; fun hammingDistance (x::xs) (y::ys) = if x = y then hammingDistance xs ys else Option.map (fn d => d + 1) (hammingDistance xs ys) | hammingDistance [] [] = SOME 0 | hammingDistance _xs _ys = NONE _xs匹配所有可能的列表,无论是空列表还是非空列表,除非它们首先与前面的模式之一匹配。因此,这第三种情况同时考虑了2. _ys[]和3。::::

    所以我不能简单地计算每个图案/身体一次。如果某些人通过模式变量包含非常通用的模式,则它们可能占一类以上的输入。如果它们通过多个构造函数包含过分具体的模式,则可能占用较少的总输入空间。例如

    []

    这里的fun pairs (x::y::rest) = (x, y) :: pairs rest | pairs [] = [] 如此具体,以至于我没有涵盖仅一个元素的情况。