Error: case object and rules don't agree [overload conflict]

Error: case object and rules don't agree [overload conflict]

我正在研究在列表中查找最大数字的函数。

fun maxValue(xs) =
  case xs of
      [] => []
    | first::rest => if ((first)>hd(rest))
                     then maxValue(first :: tl(tl(rest)))
                     else maxValue(rest)
val list = [1,2,4,8,3]
val ans = maxValue list

但是我收到以下错误:

Standard ML of New Jersey v110.78 [built: Thu Aug 31 03:45:42 2017]
= stdIn:2.5-6.40 Error: case object and rules don't agree [overload conflict]
rule domain: [> ty] list list
object: [> ty] list
in expression:
(case xs
  of :: (x,nil) => x
   | :: (xs,rest) =>
       if hd <exp> > hd <exp>
       then maxValue (<exp> :: <exp>)
       else maxValue (tl <exp>))

我不明白错误的含义,为什么代码无法编译。有没有我遗漏的东西,我该如何解决?

编辑: 为清楚起见,将某些变量名称从 xs 更改为 first。

关于你的函数我有几个问题:

  1. 你在哪里返回最大值?
  2. 你为什么想要得到 first 的脑袋?在你的例子中 first 没有头,因为它是 1,我。 e.您作为参数传递的列表的头部
  3. 你为什么要得到 rest 的尾巴?

为了解决这个 class 的递归问题,我使用了一个辅助函数,它将递归结构作为第一个参数,将可能的结果作为第二个参数。这是我的尝试:

fun maxValue xs =
  let
    fun helper xs chosen =
      case xs of
          [] => chosen
        | first :: [] =>
            if first > chosen
            then first
            else chosen
        | first :: rest =>
            if first > hd rest
            then helper rest first
            else helper rest (hd rest)
  in
    helper xs 0
  end

在空列表的情况下,我只是返回 0 以避免复杂化。

最近我使用 Poly/ML 而不是 SML/NJ。错误似乎更友好

我的教授非常友好地为我提供了以下替代解决方案和解释:

你的递归案例有几个问题:你正在获取列表第一个元素的头部,并将它与 if 语句中列表的第二个元素进行比较。然后你将你的函数应用到列表的第一个元素的头部,并与列表的第一个元素一起删除它的第一个元素?

以下是我建议如何实现此功能:

fun maxValue(xs) =
    case xs of
     x::[] => x
    | first::rest =>
          let
              val maxRest = maxValue(rest)
          in
              if first > maxRest
              then first
              else maxRest
          end

你的函数是不安全的,因为它假定 hd resttl resttl (tl rest) 具有有意义的值,但是当 rest 为空时,这些会导致 raise Empty.这里有两个安全的变体:1) maximum1 假定至少存在一个元素,但不假定它是什么。 2) maximumOpt returns NONE 当列表为空时:

fun maximum1 x xs = foldl Int.max x xs
fun maximumOpt [] = NONE
  | maximumOpt (x::xs) = SOME (maximum1 x xs)

在第一种情况下,问题在于为函数提供输入;在第二种情况下处理其输出。根据您在何处最有机会处理程序中的错误,一个或另一个可能更好。

编辑: 鉴于其他答案提供了具有各种缺点的不安全解决方案(不合理的默认值,模式匹配不详尽),这里是一个简短的变体,它会抛出一个有意义的异常:

fun maximum [] = raise Empty
  | maximum (x::xs) = foldl Int.max x xs

还有一个使用显式递归而不是折叠的:

fun maximum [] = raise Empty
  | maximum [x] = x
  | maximum (x::y::xs) = maximum (Int.max(x, y)::xs)