每月练习中的数字(SML错误:将列表中的整数与整数进行比较时,运算符和操作数不一致)

每月练习中的数字(SML错误:将列表中的整数与整数进行比较时,运算符和操作数不一致),sml,typechecking,Sml,Typechecking,我是标准ML的新手,不明白为什么会出现这种类型不匹配错误: fun number_in_month (month : int, dates : int list) = if null dates then 0

我是标准ML的新手,不明白为什么会出现这种类型不匹配错误:

fun number_in_month (month : int, dates : int list) =                                            
    if null dates                                                                                
    then 0                                                                                       
    else if (month = (hd (tl (hd dates))))            
    then number_in_month(month, (tl dates)) + 1
    else number_in_month(month, (tl dates))
评估此函数会导致以下错误:

Error: operator and operand don't agree [tycon mismatch]     
 5  operator domain: 'Z list                                                                       
 6  operand:         int                                                                           
 7  in expression:                                                                                 
 8    tl (hd dates)     
但是,在REPL,如果我执行以下操作:

val x = [[84, 12, 23], [83, 01, 18]]
12 = (hd (tl (hd x)))                    (*  -> val it = true : bool *)

我不确定这种情况下的类型检查规则是什么,我也不明白为什么相同的表达式会对REPL起作用,但在我尝试对函数中的子表达式求值时却不起作用。

您得到的是列表头部的头部和尾部。回复中的x是 整型列表整型列表的列表。但是您的函数定义声明了它 作为整型列表。用日期重新声明月份中的编号:int list应该解决 您的问题:

fun number_in_month (month : int, dates : int list list) =  
   ...
它在REPL中的工作方式与您期望的一样,因为您定义x时没有显式声明它的类型。SML推断x的类型是int list,这就是为什么hd tl hd x 通过类型检查器

更新

当stackoverflow崩溃时,他正试图添加此项

如果您感兴趣,这里有一些关于如何重新编写代码的想法 更多信息:

首先,可以使用模式匹配:

fun number_in_month (month: int, []) = 0
  | number_in_month (month: int, ([y,m,d]::rest)) = 
      if month = m then number_in_month(month, rest) + 1
      else number_in_month(month, rest)
所以number_in_month取一个月的元组和一个日期列表,逻辑上是[]或[y,m,d]::rest。这与您选择表示日期的方式是一致的 作为int的列表,但编译时会出现匹配的非穷举警告。这是有道理的,因为如果您将日期传递为[[84],[83]?模式匹配方法至少会警告您这一点,但是对于hd-tl-hd-dates这样的代码,您将得到 虽然您的程序已成功检查类型,但出现运行时错误。你可以再加一个 日期包含少于/多于3个元素的日期列表的模式匹配,但如果 可能,将日期表示为3个整数的元组会更简洁

 type date = (int * int * int)
那么你可以:

fun number_in_month (month: int, []: date list) = 0
  | number_in_month (month: int, ((y,m,d)::rest)) = 
      if month = m then number_in_month(month, rest) + 1
      else number_in_month(month, rest)
此外,如果您希望重用代码,可以尝试使用更高阶的函数,例如foldr:


比你要求的要多,但我希望它能有所帮助。

你得到的是一个列表中最重要的部分。回复中的x是 整型列表整型列表的列表。但是您的函数定义声明了它 作为整型列表。用日期重新声明月份中的编号:int list应该解决 您的问题:

fun number_in_month (month : int, dates : int list list) =  
   ...
它在REPL中的工作方式与您期望的一样,因为您定义x时没有显式声明它的类型。SML推断x的类型是int list,这就是为什么hd tl hd x 通过类型检查器

更新

当stackoverflow崩溃时,他正试图添加此项

如果您感兴趣,这里有一些关于如何重新编写代码的想法 更多信息:

首先,可以使用模式匹配:

fun number_in_month (month: int, []) = 0
  | number_in_month (month: int, ([y,m,d]::rest)) = 
      if month = m then number_in_month(month, rest) + 1
      else number_in_month(month, rest)
所以number_in_month取一个月的元组和一个日期列表,逻辑上是[]或[y,m,d]::rest。这与您选择表示日期的方式是一致的 作为int的列表,但编译时会出现匹配的非穷举警告。这是有道理的,因为如果您将日期传递为[[84],[83]?模式匹配方法至少会警告您这一点,但是对于hd-tl-hd-dates这样的代码,您将得到 虽然您的程序已成功检查类型,但出现运行时错误。你可以再加一个 日期包含少于/多于3个元素的日期列表的模式匹配,但如果 可能,将日期表示为3个整数的元组会更简洁

 type date = (int * int * int)
那么你可以:

fun number_in_month (month: int, []: date list) = 0
  | number_in_month (month: int, ((y,m,d)::rest)) = 
      if month = m then number_in_month(month, rest) + 1
      else number_in_month(month, rest)
此外,如果您希望重用代码,可以尝试使用更高阶的函数,例如foldr:


比你要求的要多,但我希望能有所帮助。

谢谢!我想出来了,但你赢了我!谢谢我想出来了,但你赢了我!