Option型

プログラミング言語と型理論において、**Option型**（）または**Maybe型**（）は存在しない可能性のある値をカプセル化して表すである。例えば、関数の戻り値が存在する場合と存在しない場合を表すためにこの型は使用される。この型は空またはオリジナルのデータ型`A`をカプセルしたコンストラクタから構成されている。

関数型プログラミング以外において、全く異なるが関連する概念としてNullable型がオブジェクト指向プログラミングで一般的である。Option型とNullable型の主な違いは、Option型はネストすることができるのに対して、Nullable型はこれに対応していないことである。

## 理論的側面

型理論において、Option型はA^{?} = A + 1のように記述することができる。これは与えられた値の組Aに対して、Option型はAの有効な値の組に正確に1つの追加の値（空の値）を追加するという事実を表している。これはを持つ言語において、Option型がカプセル化型とのタグ付き共用体として表現できるという事実によってプログラミングに反映されている。

カリー＝ハワード同型対応において、Option型は∨: x∨1=1の消滅法則に関連している。

。

Option型もモナドであり、次のようになる:


```haskell
return = Just -- Wraps the value into a maybe

Nothing  >>= f = Nothing -- Fails if the previous monad fails
(Just x) >>= f = f x     -- Succeeds when both monads succeed
```


Option型のモナディックな性質は、失敗とエラーを効率的に追跡するのに役立つ。

## 型名と定義
それぞれのプログラミング言語において、Option型は様々な名前と定義がある。

* Agdaでは、とという要素を持ち、という名前で定義されている。
* Coqでは、として定義されている。
* Elmでは、という名前でとして定義されている。
* Haskellでは、という名前でとして定義されている。
* では、として定義されている。
* OCamlでは、として定義されている。
* Pythonでは、3.10以降でまたはとして示される。
* Rustでは、として定義されている。
* Scalaでは、との型拡張によって、として定義されている。
* Standard MLでは、として定義されている。
* Swiftでは、として定義されているが、通常はとして記述される。

## 例

### F#
;コード例:
```fsharp
let compute =
    Option.fold (fun _ x -> sprintf "The value is: %d" x) "No value"

let full = Some 42
let empty = None

compute full |> printfn "compute full -> %s"
compute empty |> printfn "compute empty -> %s"
```

;実行結果:
```output
compute full -> The value is: 42
compute empty -> No value
```


### Haskell
;コード例:
```haskell
compute :: Maybe Int -> String
compute = foldl (\_ x -> "The value is: " ++ show x) "No value"

main :: IO ()
main = do
    let full = Just 42
    let empty = Nothing

    putStrLn $ "compute full -> " ++ compute full
    putStrLn $ "compute empty -> " ++ compute empty
```


;実行結果:
```output
compute full -> The value is: 42
compute empty -> No value
```


### Nim
;コード例:
```nim
import std/options

proc compute(opt: Option[int]): string =
  opt.map(proc (x: int): string = "The value is: " & $x).get("No value")

let
  full = some(42)
  empty = none(int)

echo "compute(full) -> ", compute(full)
echo "compute(empty) -> ", compute(empty)
```

;実行結果:
```output
compute(full) -> The Value is: 42
compute(empty) -> No value
```


### OCaml
OCamlは`Option`をパラメータ化された要素型として実装している。`Option`は次のように構築及び分解される:

;コード例:
```ocaml
let compute =
  Option.fold ~none:"No value" ~some:(fun x -> "The value is: " ^ string_of_int x)

let () =
  let full = Some 42 in
  let empty = None in

  print_endline ("compute full -> " ^ compute full);
  print_endline ("compute empty -> " ^ compute empty)
```

;実行結果:
```output
compute full -> The value is: 42
compute empty -> No value
```


### Rust
;コード例:
```rust
fn compute(opt: Option<i32>) -> String {
    opt.map_or("No value".to_owned(), |x| format!("The value is: {}", x))
}

fn main() {
    let full = Some(42);
    let empty = None;

    println!("compute(full) -> {}", compute(full));
    println!("compute(empty) -> {}", compute(empty));
}
```

;実行結果:
```output
compute(full) -> The value is: 42
compute(empty) -> No value
```


### Scala
Scalaは`Option`をパラメータ化された型として実装しているので、変数は`Option`になることができ、次のようにアクセスできる:

;コード例:
```scala
object Main {
  def compute(opt: Option[Int]): String =
    opt.fold("No value")(x => s"The value is: $x")

  def main(args: Array[String]): Unit = {
    val full = Some(42)
    val empty = None

    println(s"compute(full) -> ${compute(full)}")
    println(s"compute(empty) -> ${compute(empty)}")
  }
}
```

;実行結果:
```output
compute(full) -> The value is: 42
compute(empty) -> No value
```


`Option`の値を使用する方法は2つある。1つは、最良ではないが最初の例のようにパターンマッチングによる方法である。もう1つは、最良の方法である2番目の例のようなモナディックアプローチである。このように、プログラムは例外またはエラーを生成することができないので安全である。従って、これは基本的にnull値の型安全な代替手段として機能する。

### Swift
;コード例:
```swift
func compute(_ opt: Int?) -> String {
    return opt.map { "The value is: \($0)" } ?? "No value"
}

let full = 42
let empty: Int? = nil

print("compute(full) -> \(compute(full))")
print("compute(empty) -> \(compute(empty))")
```

;実行結果:
```output
compute(full) -> The value is: 42
compute(empty) -> No value
```


### Zig
;コード例:
```zig
const std = @import("std");
const print = std.io.getStdOut().writer().print;

const Compute = struct {
    value: ?i32,
    pub fn init(value: ?i32) Compute {
        return Compute{ .value = value };
    }
    pub fn format(
        self: @This(),
        comptime fmt: []const u8,
        options: std.fmt.FormatOptions,
        out_stream: anytype,
    ) !void {
        _ = fmt;
        _ = options;
        if (self.value) |n| {
            return out_stream.print("The value is: {}", .{n});
        } else {
            return out_stream.print("No value", .{});
        }
    }
};

pub fn main() !void {
    const full = Compute.init(42);
    const empty = Compute.init(null);

    try print("full -> {}\n", .{full});
    try print("empty -> {}\n", .{empty});
}
```

;実行結果:
```output
full -> The value is: 42 
empty -> No value
```

:Zigでは、`?i32` の様に型名の前に ? を追加するとOptional型となる。
:`if (opt) |n| {` の様に if 文、あるいは while文でペイロード n をキャプチャーすることができ、null の場合 else 節が評価される。

## 脚注
### 注釈

### 出典

## 関連項目
* Result型
* 
* Nullable型
* 
* 例外処理
* パターンマッチング