次のコードがあります。
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 zSome (Some y)fSomeg
この質問が正しければ、ネストされたSomes を折りたたむ関数についてです。手動で書くことができます:
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