「プログラミング in OCaml」をF#で(3)

今週も元気に進めたいと思います。
普段のエディタはKaoriYa様版GVIMを使用しており、F#のソース(*.fs)も色分けされているので微妙な違和(letとか明らかに重要なキーワードがハイライトされない、drop、maxとかはなぜかハイライトされる)を感じつつも、なんとなくそのまま使っていたのですが、そのシンタックスハイライトはForth用のものだったことが判明しました……。ちゃんと、filetype.vimocaml用の設定が適用されるように変更したらだいぶ見やすくなった。色分けされているからといって安心してはいけない。
今週は5章、再帰的多相的データ構造:リスト、の練習問題を解きました。黄色チャートをといているときの無力感を思い出した……。まぁ、数学は高一で挫折しているので、微かな記憶との比較ですが、全体に数学の参考書っぽい。このペースだといつ終わるのか全く想像もつかない……。

  • P105の練習問題。5.1、5.2はすんなり解けた
  • 5.3。集合とか出てきた。が、ここもまぁ出来た感じ
  • 5.4。map (fun x -> f (f x)) l かな?
  • 5.5。これもすんなり
  • 5.6。これを解くのに2時間以上かかった……。
let rec qsort s = function
    []  -> s
  | [x] -> x :: s
  | pivot :: rest ->
    let rec partition left right = function
        [] -> qsort (pivot :: (qsort s right)) left 
      | y :: ys -> if pivot < y then partition left (y :: right) ys
                                else partition (y :: left) right ys
  in partition [] [] rest
  • しかもこれ全部書いたわけではなく、一部分手を入れただけ。今見ると、ちゃんとヒントあるし、そこまではまる問題でもない気がするんだけど、「なんで値を二つの配列に分けた段階なのに、整列済みリストを渡せるんだ??」というところで詰まってしまった。@もでてこないし多分これであってるのでは、と思うが……。10回まわしてMeasure-Commandしたら、737msから708msで微妙に短くなってたし
  • 5.7。配列の章なので、[1..48612265]とかって配列を作ってから計算始めたら、それだけで800MBくらいメモリを使うし、そのうえ、めちゃめちゃ時間がかかる、ということに気付き、引数でチェック中の数字を渡すように変えたらすごく速くなった
  • 5.8。再帰してる部分が再帰関数の呼び出しのみになっていれば良い、のでこうだと思うんだが……。reverseは本文中で定義されてる関数。
let map2 f a = 
  let rec rec_map n = function
      [] -> n
    | x :: rest -> rec_map (f x :: n) rest in
  reverse (rec_map [] a)