5.4.4 实现选项类型的操作

5.4.4 实现选项类型的操作

 

绑定和映射的实现有类似的结构,因为,两者都是高阶函数,模式匹配依据一个选项值。我们来看一看 F# 和 C# 的实现,是在 C# 中编码函数概念的好示例。让我们从清单 6.14 开始,显示了映射操作的实现。

 

Listing 6.14 Implementing the map operation in F# and C#

F# Interactive C#

> let map f input =
     match input with
     | None �C> None
     | Some(value) �C>
       Some(f(value));;
val map :
  ('a -> 'b) �C>
   'a option -> 'b option

Option<R> Map<T, R>(this Option<T>
    input, Func<T, R> f) {
  T v;
  if (input.MatchSome(out v))
    return Option.Some(f(v));
  else
    return Option.None<R>();
}

 

    实现首先检查给定的选项值作为参数值。当值为 None,它立即返回 None 作为结果。注意,我们不能返回作为参数值的 None 值,因为类型可能不同。在 C# 版本中,更为明显。结果的类型是 Option<R>,而参数值的类型是 Option<T>。

    当参数值的值,匹配差别【送别】联合的 Some 情况,就得到 T 类型的值,并使用提供的函数(或 Func 委托),把它映射到 R 类型的值。因为,从这个操作返回的值的类型应该是 Option<R>,需要再次使用 Some 构造函数把这个值打包。

    映射和绑定操作的源代码是很相似,但也有一些重要的差异。现在让我们看一下,在清单 6.15 中的第二组操作。

 

Listing 6.15 Implementing the bind operation in F# and C#

 

F# Interactive C#

&gt; let bind f input =
     match opt with
     | None �C&gt; None
     | Some(value) -&gt; f(value)
;;
val bind :
  ('a -&gt; 'b option)
  -&gt; 'a option -&gt; 'b option

Option<R> Bind<T, R>(this Option<T>
    input, Func<T, Option&lt;R>&gt; f) {
  T value;
  if (input.MatchSome(out value))
    return f(value);
  else
    return Option.None<R>();
}

 

    绑定操作同样从模式匹配开始,依据对作为参数值给定的选项值。当选项值是 None 时,它立即返回 None,就像前面的情况一样。区别在于,当选项携带实际值。我们再次应用来自参数值的函数,但这一次,不需要把结果打包到Some构造函数中 。从函数中返回的值已经是一个选项,并且可以从类型签名中看出,这也正是我们想要返回的类型。这意味着,即使在 Some 情况下,绑定操作仍可能返回 None,具体情况要取决于用户所提供的函数。

    通常,F# 版本把原始值作为最后一个参数值,以启用流及偏应用,而 C# 版本采用扩展方法。现在,我们看一下如何在 C# 中重写前面的示例,使用新创建的方法。

 

在 C#中使用选项类型

 

    扩展方法使我们可以用流畅的风格来编写使用绑定和映射的代码。因为,括号中的数字可能会造成混乱,因此,要注意对映射的调用是嵌套在 lambda 函数内部的,作为参数值给绑定的:

 

Option<int> ReadAndAdd() {
  return ReadInput().Bind(n =&gt;
    ReadInput().Map(m =&gt; m + n));
}

 

    在 C# 中,使用高阶函数与显式处理选项类型之间的区别更为重要。C# 不直接支持类似差别联合之类的类型,但如果我们提供的类型有适当的处理函数,代码将变得可读。这是重要的一点,牢记,在 C# 中写函数式程序:一些低级的构造可能感觉不自然的,但由于 lambda 函数,我们在 C# 中也可以编写优雅的函数代码。

    到目前为止,我们已经看到了如何使用高阶函数处理多值和可选值。在前一章中,我们谈到了最后一种值是函数。在下一节,我们将看到,也可以写非常有用的高阶函数值来处理函数值。

你可能感兴趣的:(职场,笔记,休闲,hadstj)