就可以解決這個使用內置的功能:Option.bind
type A =
member this.X : B option = Unchecked.defaultof<_>
and B =
member this.Y : С option = Unchecked.defaultof<_>
and С =
member this.Z : string option = Unchecked.defaultof<_>
let a : A = Unchecked.defaultof<_>
let v =
match
a.X
|> Option.bind (fun v -> v.Y)
|> Option.bind (fun v -> v.Z) with
| Some s -> s
| None -> "<none>"
坦率地說,我對此表示懷疑,引入全面的「也許」執行(通過計算表達式),在這裏可以縮短代碼。
編輯:夢模式 - 在
我覺得版本Option.bind可以做得更小,如果F#有特殊情況更輕量級語法:拉姆達引用它的參數的一些成員:
"123" |> fun s -> s.Length // current version
"123" |> #.Length // hypothetical syntax
這是怎麼樣在Nemerle被改寫已經具有了這樣的能力:
using System;
using Nemerle.Utility; // for Accessor macro : generates property for given field
variant Option[T]
{
| Some {value : T}
| None
}
module OptionExtensions
{
public Bind[T, U](this o : Option[T], f : T -> Option[U]) : Option[U]
{
match(o)
{
| Option.Some(value) => f(value)
| Option.None => Option.None()
}
}
}
[Record] // Record macro: checks existing fields and creates constructor for its initialization
class A
{
[Accessor]
value : Option[A];
}
def print(_)
{
// shortened syntax for functions with body -> match over arguments
| Option.Some(_) => Console.WriteLine("value");
| Option.None => Console.WriteLine("none");
}
def x = A(Option.Some(A(Option.Some(A(Option.None())))));
print(x.Value.Bind(_.Value)); // "value"
print(x.Value.Bind(_.Value).Bind(_.Value)); // "none"
我很好奇你如何處理這個如果匹配表達式在不同的類型上運行,例如外部的一個選項和內部的列表......整個表達式仍然返回一個選項。 – Daniel 2010-11-01 21:38:15
你能給出一個假設的例子:源代碼和你想得到什麼結果? – desco 2010-11-01 22:06:05