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

あまりにもF#がわからず、まさにわからん殺しだったので、プログラミング in OCaml ~関数型プログラミングの基礎からGUI構築まで~をF#で練習問題解きながら進める事にしました。目標は練習問題を全部解くこと。LablTkは実行できなさそうなので、14章まで。今日は第3章まで。

  • P20
    • x +. yの替わりに x + y 使え警告
    • max_int の替わりに System.Int32.MaxValueを使いなさい警告
    • 練習問題 2.1 エラーになる式も含まれている、とあるがエラーになる式がない( + が単項演算子だから?)
    • float_of_intの替わりにfloat、int_of_floatの替わりにintを使いなさい警告
    • int_of_stringの替わりにintを使いなさい警告(しかし、intを使うと、「入力文字列の形式が正しくありません」エラー発生。謎すぎる……)
  • P21
    • int_of_float -0.7はエラーにならない(替わりにintを使え警告は出るが実行される)
    • sin 3.14 /. 2.0 ** 2.0 +. cos 3.14 /. 2.0 ** 2.0 がどう頑張っても1.0にならない……。あまりにも早い挫折。そもそも、sin、cosの意味を忘れてしまっているので、ルールが理解出来ないIQサプリをやっている気分だ……。とりあえず、sin (3.14 / 2.0) ** (2.0 + cos 3.14 / 2.0)が0.9999995244だったのでそれで先に進む……
  • P31
    • infinityの替わりに、System.Double.PositiveInfinity、nanの替わりに、System.Double.NaNを使え警告
  • P39
    • USDJPYが114.32円……
  • P51
    • 数式が出てきた……
  • P57
    • この辺から自信ない……。自信がない奴は書いておくことに。というか、ヒントの意味がわからなかった。3.7.2。
let rec pow (x:float) n =
  if n = 1 then x else
    if n % 2 = 0 then let n2 = pow x (n / 2) in n2 * n2 
                 else x * pow x (n - 1)
    • 3.8
let pow (x:float) n =
  let rec iterpow i x n = if i >= n then x else x * (iterpow (i + 1) x n) in
  iterpow 1 x n
    • 3.9。StackOverflowException。値呼びだから、else節にあたるところが無限に再帰される??
    • 3.11.1-2辺りは定義をそのままコードにすると動く感じで楽しい
    • 3.11.3。末尾再帰的関数でフィボナッチ数。elseの中で自分自身しか呼んでないからこれでいいのかな?
let fib n =
  let rec iterfib i v1 v2 n = 
    if n = 0 then 0 else
    if i >= n
      then v1
      else iterfib (i + 1) (v1 + v2) v1 n in
  iterfib 1 1 0 n
    • 3.11.4。
let max_ascii (s:string) =
 let len = (String.length s) - 1 in
 let rec iter_max i =
   if i = len
     then s.[i]
     else let max = iter_max (i + 1) in if s.[i] > max then s.[i] else max in
  iter_max 0
    • 3.12。埋め込んだだけ。これで良いのだろうか……。
let rec pos n =
  let neg = if n < 1 then 0.0 else pos (n - 1) - 1.0  / (float (4 * (n - 1) + 3)) in
  neg + 1.0 / (float (4 * n + 1))
  • P61。カリー化と擬似複数引数の話でびびる。int -> int -> int とかなってるのは、最後だけ結果の型なんだからもっと違う書き方すれば良いのに、と思っていたがそういうことなのか……
  • P67。3.14。\int_{a}^{b} f(x)dxを近似計算する関数integral f a bを作って、\int_{0}^{\pi} \sin xdxを解くという問題。計算すると2に限りなく近い値(1.999835504)になるんだけど、それで正解なのかどうかがわからない……。fun x -> x とか渡した感じだと正しい答えを返していそうな気はする。
let integral f a b =
  let n = 100.0 in 
  let delta = (b - a) / n in
  let rec trapezoid i =
    let size = ((f (a + (i - 1.0) * delta)) + (f (a + i * delta))) * delta / 2.0 in
    if i = n then size else size + trapezoid (i + 1.0) in
  trapezoid 1.0
;;
integral (fun x -> sin x) 0.0 System.Math.PI