Skip to main content

tk3++

MyList実装 mapとfilterそしてfold F#

dojo/fsharp/MyList/Program.fs at main · tk3/dojo

今日はmapとfilterそしてfoldを実装した。 foldができたということで、これまで実装したlength、sum、reverseをfoldを使い実装し直した。foldを使うとこれまでのコードが短く書けて、汎用性が高い関数であることが分かった。

例えば、foldを使うことで、次のコードが

let sum list =
    let rec loop acc currentList =
        match currentList with
        | Empty -> acc
        | Cons(x, tail) -> loop (acc + x) tail
    loop 0 list

次のように書ける。

fold (fun acc x -> acc + x) 0 list5

ただ、実装していて腑に落ちなかったことが一つ。F#の文法についてだ。

コンパイルNGのコード

110 let foldFilter f list =
111     let folded = fold (fun acc x ->
112         if f x then
113             Cons(x, acc)
114         else acc
115     ) Empty list
116
117     reverse folded

エラーメッセージはこちら

Program.fs(115,7): error FS0010: Unexpected identifier in binding. Expected incomplete structured construct at or before this point or other token.
Program.fs(111,5): error FS3118: Incomplete value or function definition. If this is in an expression, the body of the expression must be indented to the same column as the 'let' keyword.

コンパイルOKのコード

110 let foldFilter f list =
111     let folded =
112         fold (fun acc x ->
113             if f x then
114                 Cons(x, acc)
115             else acc
116         ) Empty list
117
118     reverse folded

foldの開始位置を調整したコードになってる。エラーメッセージを読めばなんとなく示唆しているのだが、最初理解ができなかった。自分にとっては直感的には理解できず、しっかりとした理解には時間がかかりそうだ。

あと、インデントは単なる見た目ではなくスコープを表しているとのこと。しっかり理解すれば後は慣れかな。