4

共通の目的を持つさまざまなタイプがたくさんありますが、それ以外の共通点はほとんどありません。説明のために、それらは次の行に沿っている可能性があります。

type blah<'a> = Blah of 'a

type huha<'a> = Huha of 'a

多くの場合、次の行に沿って関数内に入るボイラープレートの大きなチャンクを繰り返す必要があります。

let f (x:something<int>) (g:something<char> -> float) : float =

しかし、それには、型の 2 つの何かが同じであることを強制する必要があります。つまり、関数 f を次のように呼び出せるようにしたいと考えています。

f (Blah 1) (fun (b:blah<float>) -> .... )
f (Huha 1) (fun (b:huha<float>) -> .... )

明らかに、簡単な解決策は、関数 f が取り得るすべての型の判別共用体を作成し、すべての g (つまり、f の 2 番目の引数) が期待する型を取得したことを確認することです。しかし、それは、何かが変更されるたびにユニバースを再コンパイルさせる大規模な型を持つことを意味し、実行時に型をチェックすることも大いに役立つわけではありません。

それで、誰かがタイプセーフな方法で私がやりたいことをする方法を見てもらえますか? どうもありがとう。

4

1 に答える 1

2

私の知る限り、これを F# で直接行うことはできません。

しかし、おそらく演算子のオーバーロードが役立つでしょう。fただし、すべてのタイプに実装する必要があります。しかし、一般的な実装に委譲できるかもしれません。

適切な型を保証する、演算子のオーバーロードのコード例:

type T<'a> =
   | T of 'a
   static member (.+.) (l:T<int>, r:T<char> -> float) = 42.0

type U<'a> =
   | U of 'a
   static member (.+.) (l:U<int>, r:U<char> -> float) = 13.1


let ft (t:T<char>) = 42.0

let fu (t:U<char>) = 42.0

let t = T 42 .+. ft
let u = U 13 .+. fu

// does not compile:
let wrong = T 42 .+. fu
于 2012-07-28T11:07:29.287 に答える