2017-11-30 3 views
2

引数が空のリストの場合、リストモジュールの一部の関数が失敗します。 List.revは例です。問題は恐ろしい値の制限です。引数が空のリストの場合、値の制限エラーを回避するにはどうすればよいですか?

let takeAllButLast (xs: 'a list) = 
    xs |> List.take (xs.Length - 1) 

機能が空リストでうまく動作しますが、扱うでしょうバージョン:すべてが、リストの最後の要素でリストを返す関数を定義しようとしているときに、私は同じ問題を満たし

空のリストが失敗した:

let takeAllButLast (xs: 'a list) = 
    if List.isEmpty xs then [] 
    else xs |> List.take (xs.Length - 1) 
takeAllButLast [] 
error FS0030: Value restriction. The value 'it' has been inferred to have generic type 
    val it : '_a list, etc. 

を私はいくつかのことを試してみました:それインライン関数作成する引数の型を指定していない、戻り値の型を指定し、機能させるタイプの引数に依存し、使用して中間体を得るためのオプションの型結果は後でリスト< 'a>に変換されます。何も働かなかった。

はたとえば、この機能は同じ問題を抱えている:

let takeAllButLast<'a> (xs: 'a list) = 
    let empty : 'a list = [] 
    if List.isEmpty xs then empty 
    else xs |> List.take (xs.Length - 1) 

同様の質問がSOで前に頼まれた:F# value restriction in empty listが、引数が空リストである場合にのみ答えも失敗します。

空リストと空でないリストの両方を処理する関数を書く方法はありますか?

注:質問は、リストの最後の要素以外のすべてを返す関数に固有のものではありません。

答えて

3

機能自体は完全に良好です。この関数は "失敗"しません。
機能の本体を変更する必要はありません。合ってます。

この問題は、関数を呼び出すときにのみ発生します。takeAllButLast []。ここでは、コンパイラは結果にどのような型があるべきかを知らない。それはstring listであるべきですか?またはそれはint listである必要がありますか?たぶんbool list?コンパイラが知るべき方法はありません。だからそれは不平を言う。

このような呼び出しをコンパイルするには、コンパイラを手助けする必要があります。どのようなタイプが必要なのかを教えてください。これは、どちらかのコンテキストから行うことができます。

// The compiler gleans the result type from the type of receiving variable `l` 
let l: int list = takeAllButLast [] 

// Here, the compiler gleans the type from what function `f` expects: 
let f (l: int list) = printfn "The list: %A" l 
f (takeAllButLast []) 

それとも、直接呼び出し式の型を宣言することができます

(takeAllButLast [] : int list) 

それとも、機能の型を宣言し、それを呼び出すことができますが:

(takeAllButLast : int list -> int list) [] 

また、二段階でこれを行うことができます

すべての場合の原則は同じです:コンパイラはどこからあなたが期待しているタイプからを知る必要があります。また

、あなたはそれに名前を付け、その名前ジェネリックを行うことができます。

let x<'a> = takeAllButLast [] : 'a list 

このような値は、それが通常の値であるかのようにアクセスすることができますが、舞台裏で、それをパラメータなしとしてコンパイルされますジェネリック関数です。つまり、アクセスするたびにその本体が実行されます。これは、List.emptyと同様の「一般的な値」が標準ライブラリに実装されている方法です。

しかし、あなたはF#でインタラクティブな価値を評価しようとした場合はもちろん、あなたは非常に同じに直面するだろう

は再びガッチャ - タイプが知らなければなりません - あなたはとにかくそれを回避する必要があります:

> x // value restriction 
> (x : int list) // works 
+0

非常にクリアです。ありがとう。 – Soldalma

関連する問題