1

私は標準 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 で機能する理由がわかりませんが、関数内の部分式を評価しようとすると機能しません。

4

1 に答える 1

7

リストの頭の尾の頭を取得しています。あなたのx(REPLの)はint list list(intのリストのリスト)です。しかし、あなたの関数定義はそれをint list. で再宣言number_in_monthするとdates: int list list、問題が解決するはずです。

fun number_in_month (month : int, dates : int list list) =  
   ...

xタイプを明示的に宣言せずに定義するため、REPL で期待どおりに機能します。SML は x の型が 型チェッカーを通過するint list list理由であると推測します。(hd (tl (hd x)))

アップデート

(stackoverflowがダウンしたときにこの権利を追加しようとしていました)

興味がある場合は、コードを書き直してより ML っぽいものにする方法について、いくつかのアイデアを次に示します。

まず、パターン マッチングを使用できます。

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 のリストとして) 日付を表現するために選択した方法と互換性がありますが、これはmatch nonexhaustive警告付きでコンパイルされます。dates?として渡すとどうなる[[84], [83]]か パターン マッチ アプローチは、少なくともこれについて警告しますが、次のようなコードを使用すると(hd (tl (hd dates)))、プログラムの型チェックが正常に完了しても実行時エラーが発生します。日付の要素が 3 つより少ない/多い日付のリストに別のパターン マッチを追加することもできますが、可能であれば、日付を 3 つの int のタプルとして表す方がクリーンな場合があります。

 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)を試すことができます。

fun number_in_month (month: int, dates: date list) =
  foldl (fn ((_,m,_), c) => if m = month then c+1 else c) 0 dates

または

fun number_in_month (month: int, dates: date list) =
  length (List.filter (fn (_,m,_) => m = month) dates)

ご要望以上ですが、お役に立てれば幸いです。

于 2013-01-21T04:43:12.780 に答える