次のコードがあります。
let f g x = if x < 0 then None else Some(g x)
関数とともにf
、返されるg
場合と返されない場合がありOption
ます。それf
は一般的なものであり、一般的な制約がないためSome(Some(z))
、結果として発生する可能性があります。実際、私が欲しいのはまたはのいずれNone
かSome(z)
です。二重ラッピングを回避するにはどうすればよいですか (できれば に制約を課すことなくg
)?
次のコードがあります。
let f g x = if x < 0 then None else Some(g x)
関数とともにf
、返されるg
場合と返されない場合がありOption
ます。それf
は一般的なものであり、一般的な制約がないためSome(Some(z))
、結果として発生する可能性があります。実際、私が欲しいのはまたはのいずれNone
かSome(z)
です。二重ラッピングを回避するにはどうすればよいですか (できれば に制約を課すことなくg
)?
この場合、2 つの選択肢があります。g
タイプを持つか'a -> Option<'b>
、ネストされたオプション値を別々に折りたたむことを処理するかのいずれかの制約。
最初のバージョン:
let f (g: int -> Option<'b>) (x: int) =
if x < 0 then None else g x
この場合、 type の通常の関数を に渡したいときはいつでも、それを typeint -> 'b
のf
関数に持ち上げる必要がありますint -> Option<int>
。以下に例を示します。
// Simple function of type: int -> int
let plusOne = (+) 1
let y = f x (pluseOne >> Some)
2 番目の選択肢は、元の定義を維持することです。
let f (g: int -> 'b) (x: int) = if x < 0 then None else Some (g x)
必要に応じて結果を折りたたむだけです。これは、次のようにして簡単に実現できますOption.bind id
。
// This function has type: int -> Option<int>
let posPlusOne n = if n < 0 then None else Some (n + 1)
let y = f x posPlusOne |> Option.bind id
> let f g x = if x < 0 then None else Some(g x)
val f : g:(int -> 'a) -> x:int -> 'a option
f
を返します。これは、 を返すか、 などを返すことが'a option
できることを意味します。Some z
Some (Some y)
f
Some
g
この質問が正しければ、ネストされたSome
s を折りたたむ関数についてです。手動で書くことができます:
let collapseOptions x =
match x with
| Some (Some y) -> y
| _ -> None
この質問が、ネストされたすべてSome
の s を折りたたむ関数に関するものである場合、その署名を確認したいと思います:)
Maybe モナドを使う:
https://github.com/fsharp/fsharpx/blob/master/src/FSharpx.Core/ComputationExpressions/Monad.fs
let f g x =
maybe {
if x<0 then None
else
let! gx = g x
return f gx }
これを修正する最も簡単な方法は、マッチを使用することです
if x < 0 then
None
else match g x with
|Some(t) -> Some(t)
|None -> None