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。
关于你的函数我有几个问题:
- 你在哪里返回最大值?
- 你为什么想要得到
first
的脑袋?在你的例子中 first
没有头,因为它是 1
,我。 e.您作为参数传递的列表的头部
- 你为什么要得到
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 rest
、tl rest
和 tl (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)
我正在研究在列表中查找最大数字的函数。
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。
关于你的函数我有几个问题:
- 你在哪里返回最大值?
- 你为什么想要得到
first
的脑袋?在你的例子中first
没有头,因为它是1
,我。 e.您作为参数传递的列表的头部 - 你为什么要得到
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 rest
、tl rest
和 tl (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)