オプションタイプ

ウィキペディアから、無料の百科事典
ナビゲーションにジャンプ 検索にジャンプ

プログラミング言語特に関数型プログラミング言語)と型理論では、オプション型または多分型オプション値のカプセル化を表すポリモーフィック型です。たとえば、関数の戻りタイプとして使用され、適用されたときに意味のある値を返す場合と返さない場合があります。これは、空のコンストラクター(多くの場合、NoneまたはNothing)、または元のデータ型をカプセル化するコンストラクターA(多くの場合、Just Aまたは)で構成されSome Aます。

オブジェクト指向プログラミングで一般的な関数型プログラミング以外の明確であるが関連する概念は、 null許容型と呼ばれます(多くの場合、として表されますA?)。オプション型とnull許容型の主な違いは、オプション型はネスト(Maybe (Maybe A)Maybe A)をサポートしているのに対し、null許容型はサポートしていない(String??= String?)ことです。

理論的側面

型理論では、次のように書くことができます。これは、特定の値のセットに対して、オプションタイプは、次の有効な値のセットに1つの追加値(空の値)を追加します。これは、タグ付き共用体を持つ言語では、オプション型がカプセル化型とユニット型のタグ付き共用体として表現できるという事実によってプログラミングに反映されています[1]

カリー・ハワード同盟では、オプション型は∨:x∨1= 1の消滅法則に関連しています。[どうやって?]

オプションタイプは、1つまたは0の要素を含むコレクションと見なすこともできます。独自の研究?]

オプションタイプもモナドです。[2]

return  =  Just- 値を多分にラップします

  なし>> =  f =なし-前のモナドが失敗した場合は失敗します(ちょうどx)>> = f = fx-両方モナド成功場合  成功ます 
           

オプションタイプの単調な性質は、障害とエラーを効率的に追跡するのに役立ちます。[3]

名前と定義

さまざまなプログラミング言語では、オプションタイプにはさまざまな名前と定義があります。

  • Agdaでは、Maybeバリアントnothingで名前が付けられていますjust a
  • C ++ 17では、テンプレートクラスとして定義されており、空のオプションを作成するために使用できます。コンストラクターの過負荷が大きいため、モナド法に違反する可能性があります。std::optional<T>optional()
  • C#では、として定義されていますが、通常は。として記述されます。モナド法を破る。Nullable<T>T?
  • Coqでは、として定義されます。Inductive option (A:Type) : Type := | Some : A -> option A | None : option A.
  • Elmでは、名前が付けられMaybe、として定義されます。[4]type Maybe a = Just a | Nothing
  • Haskellでは、名前が付けられMaybe、として定義されています。data Maybe a = Nothing | Just a
  • Idrisでは、と定義されています。data Maybe a = Nothing | Just a
  • Javaでは、バージョン8以降、パラメーター化された最終クラスとして定義されていますモナドの法則に違反します(マップが正しく実装されていません)。[さらに説明が必要です]Optional<T>
  • ジュリアでは、という名前です。ただし、これは非推奨になりました。[5]Nullable{T}
  • OCamlでは、として定義されています。type 'a option = None | Some of 'a
  • Perl 6では、これがデフォルトですが、「スマイリー」を追加して非オプションタイプにオプトインすることができます。モナド法に違反します(ネストをサポートしません。)):D
  • Pythonでは、または3.10以降で定義されています。typing.Optional[T]T | None
  • Rustでは、と定義されています。enum Option<T> { None, Some(T) }
  • Scalaでは、とによって拡張された型として定義されています。sealed abstract class Option[+A]final case class Some[+A](value: A)case object None
  • Standard MLでは、として定義されています。datatype 'a option = NONE | SOME of 'a
  • Swiftでは、と定義されていますが、一般的にはと記述されています。[6]enum Optional<T> { case none, some(T) }T?

エイダ

Adaはオプションタイプを直接実装していませんが、レコードをパラメータ化するために使用できる識別されたタイプを提供します。オプション型を実装するには、ブール型を判別式として使用します。次の例は、制限のない制約付きタイプからオプションタイプを作成するためのジェネリックを提供します。

Generic-
  制約付きおよび制限なしのタイプ。
  タイプ Element_Type  プライベートです; 
パッケージ Optional_Type 
  -判別式Has_Elementがtrueの場合、要素フィールドがあります。
  -falseの場合、フィールドはありません(したがって、nullキーワード)。
  タイプ オプション Has_Element  Boolean    レコード
    ケース です。Has_Element 
      False => Nullの場合 です。True => Elementの場合Element_Type ; エンドケース;  
            
     
  終了レコード; 
終了 Optional_Type ;

Scala

Scalaはパラメーター化された型として実装さOptionれるため、変数はOption次のようにアクセスできます。[7]

object  Main  { 
  //この関数は、パターンマッチングを使用して `Option`s defcomputeV1を分解し
  ます opt Option [ Int ] ):String = opt match { case Some x => s"値は次のとおりです:$ x " case None => 「値なし」}   
      
         
            
    

  //この関数は、組み込みの `fold`メソッド
  defcomputeV2  opt Option [ Int ] ):String = optを使用しますfold "値なし" )(x => s "値は次のとおりです:$ x "    
      

  def  main args  Array [ String ]): Unit  =  { 
    //タイプ `Int`の` Option`である変数を定義し
    ますvalfull = Some 42 val  empty Option [ Int ] = None  
        

    // ComputeV1(full)->値は次のとおりです:42 
    println s "computeV1(full)-> $ { computeV1 full } " 

    // ComputeV1(empty)->値なし
    println s "computeV1(empty)-> $ { computeV1 empty } " 

    // ComputeV2(full)->値は次のとおりです:42 
    println s "computeV2(full)-> $ { computeV2 full } " 

    // ComputeV2(empty)->値なし
    println s "computeV2(empty)-> $ { computeV2 empty } " 
  } 
}

値を使用する主な方法は2つありますOption最初の例のように、最初の、最良ではないのは、パターンマッチングです。2番目のベストプラクティスは、2番目の例のようにモナディックアプローチです。このように、プログラムは例外やエラーを生成できないため、安全です(たとえば、にOption等しい変数の値を取得しようとすることによってNone)。したがって、これは基本的にnull値のタイプセーフな代替手段として機能します。

OCaml

OCamlOptionはパラメータ化されたバリアント型として 実装されます。Optionsは、次のように構築および分解されます。

(*この関数はパターンマッチングを使用して `option`sを分解します* 
letcompute_v1  = function | いくつかのx- > "値は次のとおりです:" ^ string_of_int x | なし-> 「値なし」  
         
     

(*この関数は組み込みの `fold`関数を使用します* 
letcompute_v2  = Option fold〜none : "値なし" 〜some :( fun x- > "は:" ^ string_of_int x  
          

let  () = 
  (*タイプ `int`の`オプション `である変数を定義します* 
  let  full  =  42in  let empty = None in
      

  (* Compute_v1 full->値は次のとおりです:42 *)
  print_endline  "compute_v1 full->"  ^  Compute_v1  full );

  (* Compute_v1 empty->値なし*)
  print_endline  "compute_v1 empty->"  ^  Compute_v1  empty );

  (* Compute_v2 full->値は次のとおりです:42 *)
  print_endline  "compute_v2 full->"  ^  Compute_v2  full );

  (* Compute_v2 empty->値なし*)
  print_endline  "compute_v2 empty->"  ^  Compute_v2  empty 

F#

//この関数は、パターンマッチングを使用して、 `option`sを分解し
ます。letcompute_v1  = function | いくつかのx- > sprintf "値は次のとおりです:%d" x | なし-> 「値なし」  
          
       

//この関数は、組み込みの `fold`関数letcompute_v2 
= Option 使用します。fold fun _ x- > sprintf "値は次のとおりです:%d" x "値なし" 
            

//タイプ `int`の` option`sである変数を定義し
ますletfull = Some 42 let  empty = None   
   

// Compute_v1full->値は次のとおりです。42compute_v1full 
|> printfn " compute_v1  full  ->%s"  

// compute_v1が空です->値がありません
compute_v1が 空です |>  printfn  "compute_v1 empty->%s"

// Compute_v2full->値は次のとおりです。42compute_v2full 
|> printfn " compute_v2  full  ->%s"  

// compute_v2が空です->値がありません
compute_v2が 空です |>  printfn  "compute_v2 empty->%s"

Haskell

-この関数はパターンマッチングを使用して `Maybe`scomputeV1を分解し
ます:: Maybe Int-  > StringcomputeV1 Just x = "値は次のとおりです: " ++ show xcomputeV1 Nothing = " No value "    
       
    

-この関数は組み込みの `foldl`関数を使用します
computeV2 :: たぶん Int-  >  StringcomputeV2  = 
foldl  \ _ x- > "値は次のとおりです: " ++ show x " No value "         

main  ::  IO  ()
main  =  do-
    タイプ `Int`の`多分 `である変数を定義し
    ますletfull = Just 42 let  empty = Nothing   
       

    --computeV1full->値は次のとおりです
    。42putStrLn  $  "computeV1 full->"  ++  ComputeV1  full

    --computeV1full->値なし
    putStrLn  $  "computeV1 empty->"  ++  ComputeV1  empty

    --computeV2full->値は次のとおりです
    。42putStrLn  $  "computeV2 full->"  ++  ComputeV2  full

    --computeV2full->値なし
    putStrLn  $  "computeV2 empty->"  ++  ComputeV2  empty

Swift

//この関数は、 `switch`ステートメントを使用して` Optional`の
funccomputeV1  _ opt Int ?)-> String { switch opt { caseを分解しますsome let x ):return "値は:\(x " case none 「値なし」を返します} }     
      
      
         
     
         
    


//この関数は、オプションのバインディングを使用して `Optional`s 
funccomputeV2を分解し ます_  opt  Int ?) ->  String  { 
    if  let  x  =  opt  { 
        return  " The value is:\(x " 
    }  else  { 
        return  " No value " 
    } 
}

//タイプ `Int`の` Optional`である変数を定義し
ますletfull  Int = 42空にするInt _ = nil   
    

// ComputeV1(full)->値は次のとおりです:42 
print "computeV1(full)-> \(computeV1 full ))" 

// ComputeV1(empty)->値なし
print "computeV1(empty)-> \(computeV1 empty ))" 

// ComputeV2(full)->値は次のとおりです:42 
print "computeV2(full)-> \(computeV2 full ))" 

// ComputeV2(empty)->値なし
print "computeV2(empty)-> \(computeV2 empty ))" 

さび

//この関数は、 `match`式を使用して` Option`のfncompute_v1を分解し
ます opt Option < i32 > -  > String  {
    マッチオプト{  
        いくつかのx =>フォーマット!"値は:{}" x )、   
        なし=> 「値なし」to_owned ()、  
    }
}

//この関数は、 `iflet`式を使用して` Option`のfncompute_v2 
 opt  Option < i32 > - >  String { を分解します。
    Some x = opt { _ _     
        フォーマット!"値は次のとおりです:{}" x  
    } else {  
        「値なし」to_owned ()
    }
}

//この関数は、組み込みの `map_or`メソッドを使用します
fncompute_v3  opt Option < i32 > - > String {  
    opt map_or "値なし" 。to_owned )、| x | format!"値は:{}" x ))   
}

fn  main (){ 
    //タイプ `i32`の` Option`である変数を定義します
letfull = Some 42 ;       
    空にするオプション< i32 > =なし; _   

    // Compute_v1(&full)->値は次のとおりです:42 
println!"compute_v1(&full)-> {}" compute_v1 full ));     

    // Compute_v1(&empty)->値なし
println!"compute_v1(&empty)-> {}" compute_v1 empty ));     

    // Compute_v2(&full)->値は次のとおりです:42 
println!"compute_v2(&full)-> {}" compute_v2 full ));     

    // Compute_v2(&empty)->値なし
println!"compute_v2(&empty)-> {}" compute_v2 empty ));     

    // Compute_v3(&full)->値は次のとおりです:42 
println!"compute_v3(&full)-> {}" compute_v3 full ));     

    // Compute_v3(&empty)->値なし
println!"compute_v3(&empty)-> {}" compute_v3 empty ))     
}

ニム

インポート オプション


#このprocは、組み込みの `isSome`および` get`procを使用して `Option`のproccompute opt Option  [ int ]  string  = 
  ifoptを分解し ますisSome 
    "値は:"   $ opt に取得
  「値なし」
    

#タイプ `Int`の`オプションの変数を定義
するletfull 
  = some 42 empty = none int   
    

#compute(full)->値は次のとおりです
。42echo  "compute(full)->"  compute full 

#compute(empty)->値なし
echo  "compute(empty)->"  compute empty 

も参照してください

参考文献

  1. ^ Milewski、Bartosz(2015-01-13)。「単純な代数的データ型」BartoszMilewskiのプログラミングカフェ合計タイプ。「多分次のようにエンコードすることもできます:データ多分a =どちらか()a」。2019-08-18にオリジナルからアーカイブされました2019年8月18日取得
  2. ^ 「一握りのモナド-偉大な善のためのハスケルを学びましょう!」www.learnyouahaskell.com 2019年8月18日取得
  3. ^ ハットン、グラハム(2017年11月25日)。「モナドとは?」ComputerphileYoutube2021年12月20日にオリジナルからアーカイブされました2019年8月18日取得
  4. ^ 「たぶん・エルム入門」guide.elm-lang.org
  5. ^ 「Juliav0.7.0リリースノート・Julia言語」docs.julialang.org
  6. ^ 「AppleDeveloperDocumentation」developer.apple.com 2020年9月6日取得
  7. ^ マーティンオーダスキー; レックススプーン; ビルベナーズ(2008)。ScalaでのプログラミングArtima Inc. pp。282–284。ISBN 978-0-9815316-0-12011年9月6日取得