あなたのコードの問題点をどこから指摘したらよいかさえわかりません。関数型プログラミングの基本を誤解しているようです。
- まず、参照を使用すべきではありません (自分が何をしているのかわかっていない限り、おそらくまだ間違っている可能性があります)、再帰を使用する必要があります。
- 同じ数の引数を取るように関数を宣言していません。最初の節では、2 つのカリー化された引数を使用して定義し、残りの節では 1 つの引数しか持たず、コードの最後の 2 行目では、ペアを引数として関数を呼び出しています。
- 最初の関数句には本体がありません。
"<"
sml の厳密なより小さい演算子ではありません。あなたがそこに書いたように、それは文字列です。
元のコードを修正すると、このような結果になります。最初の要素は常にリストに戻されることに注意してください。これにより、何と比較するかがわかります。
fun findlarger [] = 0
| findlarger [x] = 0
| findlarger (x::y::xs) =
if y > x*2 then
1 + findlarger(x :: xs)
else
findlarger(x :: xs)
ただし、内部ヘルパー関数を使用して x*2 の計算を行うこともできるため、毎回計算されるわけではありません。
fun findlarger [] = 0
| findlarger (x::xs) =
let
val xx = 2*x
fun f [] = 0
| f (y::ys) =
(if y > xx then 1 else 0) + f ys
in
f xs
end
他の回答で提案されているように高次関数を使用する場合は、リストを2回トラバースすることを避ける必要があります(最初に要素を除外してから残りを数えます)。リストを一度調べて、特定の述語に一致する要素を数えるだけです。
この機能を実現するには、fold 関数の 1 つを使用できます。ほとんどの場合、foldl を使用するのが理にかなっています。これは、リストを左から右に末尾再帰的にトラバースするためです。
fun p (x, y) = if y > 2*x then 1 else 0
fun f [] = 0
| f (x::xs) = foldl (fn (a,b) => b + p(x, a)) 0 xs