3

次のコードがあります。

let f g x = if x < 0 then None else Some(g x)

関数とともにf、返されるg場合と返されない場合がありOptionます。それfは一般的なものであり、一般的な制約がないためSome(Some(z))、結果として発生する可能性があります。実際、私が欲しいのはまたはのいずれNoneSome(z)です。二重ラッピングを回避するにはどうすればよいですか (できれば に制約を課すことなくg)?

4

5 に答える 5

3

この場合、2 つの選択肢があります。gタイプを持つか'a -> Option<'b>、ネストされたオプション値を別々に折りたたむことを処理するかのいずれかの制約。

最初のバージョン:

let f (g: int -> Option<'b>) (x: int) = 
    if x < 0 then None else g x

この場合、 type の通常の関数を に渡したいときはいつでも、それを typeint -> 'bf関数に持ち上げる必要があります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
于 2013-09-28T20:54:10.283 に答える
3
> 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 を折りたたむ関数に関するものである場合、その署名を確認したいと思います:)

于 2013-09-28T03:39:15.807 に答える
2

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 }
于 2013-09-30T04:17:22.963 に答える
2

これを修正する最も簡単な方法は、マッチを使用することです

if x < 0 then
    None
else match g x with
     |Some(t) -> Some(t)
     |None -> None
于 2013-09-28T03:07:27.527 に答える