は、F#でオプションタイプです:オプションの種類が崩壊しますか?ここ
type Option<'a> =
| Some of 'a
| None
は、私がOption
のOption
があるとします。
type Option2<'a> =
| O of Option<'a>
| None
それはちょうど1 Option
まで崩壊しますしていますか?
は、F#でオプションタイプです:オプションの種類が崩壊しますか?ここ
type Option<'a> =
| Some of 'a
| None
は、私がOption
のOption
があるとします。
type Option2<'a> =
| O of Option<'a>
| None
それはちょうど1 Option
まで崩壊しますしていますか?
いいえ、F#は公称タイプのシステムです。 構造的に相当のタイプは互換性がありません。したがって、Option
とOption2
が全く同じ(名前を除いて)あっても、これらのタイプは異なります。あなたの場合は、intのリストとintのリストのリストが同じかどうかを尋ねるのと同じように異なります。
let hasOptionType (_ : Option<_>) =()
let hasOption2Type (_ : Option2<_>) =()
let o = Option.None
let o2 = Option2.None
hasOptionType o
//hasOption2Type o // does not compile
//hasOptionType o2 // does not compile
hasOption2Type o2
その仕事は、両方の方法けれどもあなたは、型の別名を持つことができます。
type IntOption = Option<int>
let isOptionOfInt (_ : Option<int>) =()
let isIntOption (_ : IntOption) =()
let i = IntOption.None
let i2 = Option<int>.None
isOptionOfInt i
isOptionOfInt i2
isIntOption i
isIntOption i2
いいえ、あなたが定義したオプションの種類を自動的に他のいくつかのタイプにマージされることはありません。彼らは別々の弁別された組合であり、そのように扱われなければならない。
どのようにパターンマッチしなければならないとOption2
の値を構築示しており、以下の例を見てみましょう:あなたはOption
のOption
について話すが、その後のタイプを示しているため、あなたの質問は少し混乱して
let info x = match x with
| O (Some i) -> sprintf "Found %d" i
| O (Option.None) -> "The wrapping Option2 contained None"
| Option2.None -> "The wrapper was None"
System.Console.WriteLine(info (O (Some 3)))
System.Console.WriteLine(info (O Option.None))
System.Console.WriteLine(info Option2.None)
// prints:
// Found 3
// The wrapping Option2 contained None
// The wrapper was None
Option
を含むあなた自身のOption2
タイプです。
私はあなたの質問が本当にこれと仮定します:Some (Some x)
はSome x
に崩壊しますか?
その答えはいいえです。その崩壊は暗黙的に型を変更し、Option
が提供する型の安全性の一部を失うことになります。また、折りたたまれたバージョンと折りたたまれていないバージョンの区別は重要です。この例を考えてみましょう。
match List.tryHead [Some 1; None; Some 2] with
| Some (Some x) -> sprintf "The first item exists with a value of %i" x
| Some None -> "The first item exists but it has no value"
| None -> "The list was empty"
List.tryHead
関数はリストの最初の要素を返します。リストが空の場合はNoneを返します。 Option<int>
のリストを渡していますので、返す値はOption<Option<int>>
戻り値の型が異なる可能性のあるすべてのケースをカバーするために、戻り値を照合することができます。これらのケースを別々に扱いたい場合には、これは便利です。
しかし、我々はまだ同等としてSome None
とNone
を治療する能力を持っている:
match List.tryHead [Some 1; None; Some 2] with
| Some (Some x) -> sprintf "The first item exists with a value of %i" x
| _ -> "No value found"
いいえ、それはしません。それは本当に奇妙な行動でしょう。また、最初のケースには名前がないため、2番目の定義はコンパイルされません。 –
お試しあればどうなりますか? –
FWIWでは、* bind *: 'Some(Some 42)|> Option.bind id'で通常の' option'値を 'Some 42'に簡単に '平坦化'できます。 –