2016-10-09 8 views
4

で、リストの最後の要素を取得し、私のロジックは、リストを逆にすると、その頭を得ることです:私は、リストの最後の要素を取得したい、F#

module Program1 = 

    let last list = 
     let newList=List.rev list; 
     List.head newList; 
     newList 

    let mainP1()= 
     let list= [ 1; 2; 3] 
     printfn "Ultimul element al listei %A este %A" list (last list) 

が、それは私にこのエラーが発生します

Error  Type mismatch. Expecting a 
    unit list  
but given a 
    int list  
The type 'unit' does not match the type 'int' 

誰でもお手伝いできますか?

+1

「List.last」の組み込み関数があります。この宿題ですか? –

答えて

5

ここに解凍するにはかなりのことがあります。

最初のは、あなたの関数が返すものを返していません。最後の行は、newListと書かれていますか?これが関数の戻り値です。関数本体の最後の行は戻り値です。したがって、最後の要素ではなく、逆のリストを返しています。第二

、あなたがList.head呼び出しの結果を返していないことから、あなたはがそれをを無視しています。その結果と何もしない。無視する。そして、F#コンパイラはここであなたを助けようとします:あなたが値を無視しているなら、それはあなたが何か間違っていることを意味し、そうするならF#は文句を言うでしょう(警告を出します)。

ただし、そのルールには例外が1つあります。unitの値は無視できます。論理は、タイプunitの値を持っている場合は、副作用の結果として取得したに違いありません。副作用がなく、結果として価値がない場合(unitは「価値なし」を意味する)、その点は何ですか?

したがって、コンパイラは次のように考えます。値を無視した場合、値はunitである必要があります。 List.head newListunitのタイプであるため、newListunit listである必要があります。したがって、listunit listである必要があります。したがって、関数のタイプはunit list -> unit list(つまり、パラメータとしてunit listをとり、結果としてunit listを返します)。

int listunit listという関数に渡そうとしているので、コンパイラはそれに耐えられません:Expecting a unit list but given a int list

最後にで、最後の値になるようにリストを逆転させるのは非常に無駄です!あなたは本当に必要のないたくさんの記憶を再割り当てしています。これを達成するための無駄の少ない方法は、再帰の使用によるものです。このように考える:1要素リストの最後の要素は1要素であり、長いリストの最後の要素はその末尾の最後の要素です。私たちは、ストレートF#でそれを書くことができます。

let rec last list = 
    match list with 
    | [x] -> x // The last element of one-element list is the one element 
    | _::tail -> last tail // The last element of a longer list is the last element of its tail 
    | _ -> failwith "Empty list" // Otherwise fail 

Plusは、(これは宿題がある場合を除き、その場合に問題になっていることを言及する必要があります)あなただけ使用することができ、既製の機能List.lastあります。

let mainP1()= 
    let list= [ 1; 2; 3] 
    printfn "Ultimul element al listei %A este %A" list (List.last list) 

リストに最後の要素がない可能性があります(リストが空の場合)。この場合、List.last(およびList.head)は例外でクラッシュしますが、これは一般的には良い考えではありません。空リストの場合を処理する必要がある場合は、

let mainP1()= 
    let list= [1; 2; 3] 
    match List.tryLast list with 
    | Some x -> printfn "Ultimul element al listei %A este %A" list x 
    | None -> printfn "Lista %A este goală" list 
+3

「FSharp.Collections.List <'T>」と呼ばれる変更不可能なリンクリストは、ランダムアクセスには効率的ではありません。リスト全体が横断されなければならず、したがってO(n)です。 'List.rev'はそれより良くないか悪いです。 – kaefer

+0

あなたは正しいです。なんらかの理由で、私はF#がパフォーマンスのためにそこで騙されたという印象を受けました[List.mapでのやり方](https://github.com/fsharp/fsharp/blob/84b6da1bfcdc748ba1a79444f70e04708c6d3324/src/fsharp/FSharp.Core/ local.fs#L238)、しかし明らかにそうではありません。私は答えからこの点を削除します。 –

関連する問題