9

我仍然是 Scala 开发的菜鸟,但我发现Option[T]概念真的很棒,特别是与 Some 和 None 一起使用时的模式匹配。我什至在某种程度上在我正在处理的 C# 项目中实现它,但是由于没有模式匹配,所以并不是那么棒。

真正的问题是,这个物体背后的理论在哪里?它是 Scala 特有的吗?功能语言?我在哪里可以找到更多关于它的信息?

4

3 回答 3

13

大多数时候我认为它来自 Haskell,并且有一个名字Maybe monad

但经过一番研究,我发现在 SML 论文中有一些关于选项类型的参考,正如@ShiDoiSi 所说。此外,它具有与 Scala 相同的语义(Some/None)。我能找到的最古老的论文是大约 89 年)(见第 6 页的脚注)

于 2012-02-06T20:55:20.273 回答
8

您不需要模式匹配即可使用 Option。我在下面为您用 C# 编写了它。请注意,该Fold函数负责处理其他模式匹配的任何内容。

通常不鼓励模式匹配以支持更高级别的组合器。例如,如果可以使用您的特定函数编写,Select您将使用它而不是Fold(这相当于模式匹配)。否则,假设没有副作用的代码(因此,等式推理),您基本上将重新实现现有代码。这适用于所有语言,而不仅仅是 Scala 或 C#。

using System;
using System.Collections;
using System.Collections.Generic;

namespace Example {
  /// <summary>
  /// An immutable list with a maximum length of 1.
  /// </summary>
  /// <typeparam name="A">The element type held by this homogenous structure.</typeparam>
  /// <remarks>This data type is also used in place of a nullable type.</remarks>
  public struct Option<A> : IEnumerable<A> {
    private readonly bool e;
    private readonly A a;

    private Option(bool e, A a) {
      this.e = e;
      this.a = a;
    }

    public bool IsEmpty {
      get {
        return e;
      }
    }

    public bool IsNotEmpty{
      get {
        return !e;
      }
    }

    public X Fold<X>(Func<A, X> some, Func<X> empty) {
      return IsEmpty ? empty() : some(a);
    }

    public void ForEach(Action<A> a) {
      foreach(A x in this) {
        a(x);
      }
    }

    public Option<A> Where(Func<A, bool> p) {
      var t = this;
      return Fold(a => p(a) ? t : Empty, () => Empty);
    }

    public A ValueOr(Func<A> or) {
      return IsEmpty ? or() : a;
    }

    public Option<A> OrElse(Func<Option<A>> o) {
      return IsEmpty ? o() : this;
    }

    public bool All(Func<A, bool> f) {
      return IsEmpty || f(a);
    }

    public bool Any(Func<A, bool> f) {
      return !IsEmpty && f(a);
    }

    private A Value {
      get {
        if(e)
          throw new Exception("Value on empty Option");
        else
          return a;
      }
    }

    private class OptionEnumerator : IEnumerator<A> {
      private bool z = true;
      private readonly Option<A> o;
      private Option<A> a;

      internal OptionEnumerator(Option<A> o) {
        this.o = o;
      }

      public void Dispose() {}

      public void Reset() {
        z = true;
      }

      public bool MoveNext() {
        if(z) {
          a = o;
          z = false;
        } else
          a = Option<A>.Empty;

        return !a.IsEmpty;
      }

      A IEnumerator<A>.Current {
        get {
          return o.Value;
        }
      }

      public object Current {
        get {
          return o.Value;
        }
      }
    }

    private OptionEnumerator Enumerate() {
      return new OptionEnumerator(this);
    }

    IEnumerator<A> IEnumerable<A>.GetEnumerator() {
      return Enumerate();
    }

    IEnumerator IEnumerable.GetEnumerator() {
      return Enumerate();
    }

    public static Option<A> Empty {
      get {
        return new Option<A>(true, default(A));
      }
    }

    public static Option<A> Some(A t) {
      return new Option<A>(false, t);
    }
  }
}
于 2012-02-07T00:24:02.920 回答
7

维基百科是你的朋友:http ://en.wikipedia.org/wiki/Option_type

不幸的是,它没有给出任何日期,但我敢打赌它的 ML 起源早于 Haskell 的Maybe.

于 2012-02-06T21:01:18.293 回答