-1

month_range入力として 1 年の 2 日 (たとえば、1 年が 365 日であると仮定すると 65 と 128) を取り、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_rangeが then 分岐でリストを返すため、else 分岐でもリストを返す必要があります。私たちはそれを修正します。

現在、関数は day1 が属する月の番号のみを返します (理論的には、まだ入力されていないため)。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 に答える