2017-11-23 17 views
1

リストを与えられた入力を持つ要素の連続した出現が1になるリストを返す単純な関数を構築しました。値の制限と型推論

let rec reduce l = 
match l with 
| []    -> [] 
| [x]    -> [x] 
| x::(y::_ as xs) -> if x = y then 
          reduce xs 
         else 
          x::(reduce xs) 


# reduce [1;1;2;2;2;3;3;4;3;3;3];; 
- : int list = [1;2;3;4;3]. 
# reduce [’a’;’a’;’a’;’b’];; 
- : char list = [’a’; ’b’]. 
# reduce [];;    // The case 
- : ’a list = [] 

空のリストを除き、すべてが期待通りに動作します。[]入力。苦情申告者はエラーFS0030:値の制限と述べています。私はdocumentationを通して現象の理解を深めようとしましたが、ポイントを正しく得る技術はまだ持っていないような気がします。汎用関数で[]の型を指定する必要があるのはなぜですか?結果は[]は型推論なしで単純に報告できませんでしたか?そして、最後に、そのような事件を封じ込めるために、どのように機能を構造化すべきか?

+0

問題は、[[] 'は' 'リスト 'ですが、コンパイラは' 'a''が何であるかを知る必要があります –

+0

あなたの貢献のために@JohnPalmerありがとうございます。 – Worice

答えて

2

コメントでJohnが言ったように、問題は、[]は、リストの型が何であるかについてコンパイラに何のヒントも与えていないということです。それ以外の場合は整数の文字リストですが、タイプは分かっていません。

未知のジェネリック型が関係するF#コードを実行することはできないため、コードを実行してジェネリックリストを取得する方法はありません。コードを実行するときは、すべての型を完全に指定する必要があります。

あなたはタイプを修正するためのいくつかの方法で、型注釈を提供することができます:今汎用コードが他の一般的な内部にあるので、あなたはまた、コンパイル別の汎用関数への呼び出しをラップすることができ

reduce ([] : int list) 
(reduce [] : int list) 
(reduce:int list -> _) [] 

を使用するために、タイプを必要とする関数:

let foo() = reduce [] 

しかし、今あなたは同じ問題を抱えている - あなたはfooを呼び出すときに型を指定する必要があり、またはコンパイラが文脈からそれを推測できるようにする必要があり、例えばあなたが書いた場合1 :: foo()

+0

トマにありがとう。あなたのわかりやすい説明のために、今私は確かに問題のより良い理解を持っています。 – Worice