F# についてさらに学ぶために、Paul Grahamがここで説明している「アキュムレータ ジェネレーター」を実装しようとしました。これまでのところ、私の最善の解決策は完全に動的に型付けされています。
open System
let acc (init:obj) : obj->obj=
let state = ref init
fun (x:obj) ->
if (!state).GetType() = typeof<Int32>
&& x.GetType() = typeof<Int32> then
state := (Convert.ToInt32(!state) + Convert.ToInt32(x)) :> obj
else
state := (Convert.ToDouble(!state) + Convert.ToDouble(x)) :> obj
!state
do
let x : obj -> obj = acc 1 // the type annotation is necessary here
(x 5) |> ignore
printfn "%A" (x 2) // prints "8"
printfn "%A" (x 2.3) // prints "10.3"
3 つの質問があります。
- の型注釈を削除する
x
と、コンパイラはint -> obj
x の型を推測するため、コードはコンパイルに失敗しますが、acc
を返すように注釈が付けられていobj->obj
ます。それはなぜですか?また、回避できますか? - この動的に型付けされたバージョンを改善するためのアイデアはありますか?
- これを適切な静的型で実装することは可能ですか? 多分メンバーの制約がありますか?(Haskell では可能ですが、OCaml では不可能です)