-1

我有一个名为的函数month_range,它需要一年中的两天作为输入(例如,65 和 128,假设一年有 365 天)并返回一个列表,其中包含从 day1 到 day2 的天数所属的月份数。

列表的大小必须为“day2 - day1 + 1”。

示例:month_range(25,35) 应返回:[1,1,1,1,1,1,1,2,2,2,2]

我写了以下代码

fun month_range (day1:int,day2:int) =
    let
      val month_days= [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
      fun what_month(day :int) =
          let
            fun aux(sum :int,  numbers: int list) =
                let
                  val numbers_tail = tl numbers
                in
                  if sum <= (hd numbers)
                  then 1
                  else
                    1 + aux(sum, (hd numbers + hd numbers_tail)
                            :: (tl numbers_tail))
                end
          in
            aux(day, month_days)
          end
    in
      if (day1>day2)
      then []
      else what_month(day1) @ what_month(day1 + 1)@::what_month(day2)
    end

但它给了我以下错误

/tmp/emacs-region5156f3r:21.51-21.54 Error: unbound variable or constructor: @::
/tmp/emacs-region5156f3r:21.12-21.70 Error: operator is not a function [literal]
  operator: int
  in expression:
    (what_month (day1 + 1)) <errorvar>
/tmp/emacs-region5156f3r:21.12-21.70 Error: operator and operand don't agree [literal]
  operator domain: 'Z list * 'Z list
  operand:         int * _
  in expression:
    what_month day1 @ (((what_month <exp>) <errorvar>) what_month) day2

uncaught exception Error
  raised at: ../compiler/TopLevel/interact/evalloop.sml:66.19-66.27
             ../compiler/TopLevel/interact/evalloop.sml:44.55
             ../compiler/TopLevel/interact/evalloop.sml:296.17-296.20
4

1 回答 1

2

首先,您可以从错误消息中看到您正在使用@::,这实际上没有任何意义。

您很可能已经what_month为另一个赋值创建了该函数,因此没有理由将它放在 let 表达式中。

现在,如果我们稍微简化一下您的代码

val month_days= [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
fun what_month(day :int) =
    let
      fun aux(sum :int,  numbers: int list) =
          let
            val numbers_tail = tl numbers
          in
            if sum <= (hd numbers)
            then 1
            else
              1 + aux(sum, (hd numbers + hd numbers_tail)::(tl numbers_tail))
          end
    in
      aux(day, month_days)
    end


fun month_range (day1:int,day2:int) =
      if (day1>day2)
      then []
      else what_month(day1)

然后我们会看到它仍然没有输入。这是因为what_month函数的类型是int -> int,但是您在主体内的 if 表达式在month_rangethen 分支中返回一个列表,那么您还必须在 else 分支中返回一个列表。我们会解决这个问题。

目前该函数仅返回 day1 所属的月份数(理论上,as is 尚未键入)。我们不希望它返回所有 day1 ... day2 的列表。
这就是递归的用武之地。如果我们what_month(day1)与递归调用串联返回,month_range( day1 + 1, day2)那么我们最终将建立一个列表

what_month(day1) :: what_month(day1 + 1) :: what_month(day1 + 1 + 1) ...

并且由于您返回空列表,因此当您达到条件时day1 > day2,递归将为您提供这样的结果

what_month(day1) :: what_month(day1 + 1) :: what_month(day1 + 1 + 1)  :: ...
                 :: what_month(day2) ::[]

生成的代码如下所示

fun month_range (day1:int,day2:int) =
    if (day1>day2)
    then []
    else what_month(day1) :: month_range(day1 + 1, day2)

- month_range(25,35);
val it = [1,1,1,1,1,1,1,2,2,2,2] : int list
于 2013-04-05T12:22:29.327 回答