2017-10-10 6 views
2

listintの場合、listのすべての要素の合計を返します。これは、ある述語pを満たしています。F#すべての整数をリストに集計する

私はこれまでに来ましたが、それほどまだありません。コンパイラは、メッセージに0に文句を言う:私は何をしないのですThe type 'int' does not match the type 'int list -> 'a''

let sum (p, xs) = 
    let rec sum' p xs tempSum = function 
     | []  -> tempSum 
     | x::xs  -> sum' p xs tempSum + (if p x then x else 0) 
    sum' p xs 0 

+3

'List.filter pを要求される場合|> List.sum'? –

答えて

4

あなたsum'機能が...は、あなたが(xsあなたの場合)に一致したい変数であるmatch ... with構文伊勢それを修正するために、xs変数にパターンマッチングではありません - 型の不一致がによって解決されなければなりませんそれ。

2
let sum p xs = 
    xs 
    |> List.sumBy (fun x -> if p x then x else 0) 
2

あなたのコードには、同じ結果が出ているので気づいていないもう1つの間違いがあります。現在書かれているように、あなたのコードはtail-recursiveではありません。これは、関数アプリケーションが+のような演算子よりも優先順位が高いためです。だからあなたのコードで表現sum' p xs tempSum + (if p x then x else 0)のように解釈されている:あなたはおそらくだった望んとき

(sum' p xs tempSum) + (if p x then x else 0) 

sum' p xs (tempSum + (if p x then x else 0)) 

あなたがそれを書いた方法で、ネストされたsum'呼び出しの結果にすることはできません再帰呼び出しが戻った後に追加が行われてからすぐに返され、各呼び出しがスタックフレームをとり、何千もの項目のリストでコードが失敗することになります。あなたの追加の周りにカッコを追加することによって、おそらくあなたが望んでいたテールコールの最適化が得られます。

0
let sum f = List.fold (fun s x -> if f x then s + x else s) 0 

または、末尾再帰は

let sum f xs = 
    let rec aux acc = function 
     | [] -> acc 
     | x::xs when f x -> aux (x + acc) xs 
     | _::xs -> aux acc xs 
    aux 0 xs 
関連する問題