これは実際には、たまたまPreludeで定義されている通常のデータコンストラクターに過ぎません。これは、すべてのモジュールに自動的にインポートされる標準ライブラリです。
多分、構造的に
定義は次のようになります。
data Maybe a = Just a
| Nothing
その宣言は、型Maybe a変数によってパラメーター化される型を定義しますa。これは、の代わりに任意の型で使用できることを意味しますa。
構築と破壊
型には2つのコンストラクターとがJust aありNothingます。型に複数のコンストラクターがある場合、それは型の値が可能なコンストラクターの1つだけで構成されていなければならないことを意味します。このタイプの場合、値はJustまたはを介して構築されNothing、他の(エラーではない)可能性はありません。
Nothingパラメータ型がないため、コンストラクタとして使用される場合Maybe a、すべての型の型のメンバーである定数値を指定しますa。ただし、Justコンストラクターには型パラメーターがあります。つまり、コンストラクターとして使用すると、型aからへの関数のように機能しますMaybe a。つまり、型がa -> Maybe a
したがって、型のコンストラクターはその型の値を作成します。もう一方は、その値を使用したい場合であり、パターンマッチングが重要な役割を果たします。関数とは異なり、コンストラクターはパターンバインディング式で使用できます。これは、複数のコンストラクターを持つ型に属する値のケース分析を行うことができる方法です。
Maybe aパターンマッチで値を使用するには、次のように、コンストラクタごとにパターンを指定する必要があります。
case maybeVal of
Nothing -> "There is nothing!"
Just val -> "There is a value, and it is " ++ (show val)
その場合の式では、最初のパターンは値がの場合に一致Nothingし、2番目のパターンは値がで構成された場合に一致しJustます。2番目のものも一致する場合は、一致する値が作成されたときにコンストラクターにval渡されたパラメーターに名前もバインドしJustます。
たぶん意味
たぶん、あなたはすでにこれがどのように機能するかを知っていました。実際にはMaybe値に魔法はありません。それは通常のHaskell Algebraic Data Type(ADT)にすぎません。ただしInteger、例からなど、型を効果的に「リフト」または拡張して、値Nothingの欠如を表す追加の値()を持つ新しいコンテキストに拡張するため、かなり使用されています!型システムではInteger、そこにある可能性のある値に到達する前に、その追加の値を確認する必要があります。これにより、驚くべき数のバグが防止されます。
今日、多くの言語がこのような「値なし」の値をNULL参照で処理しています。著名なコンピュータサイエンティストであるトニーホアレ(彼はQuicksortを発明し、チューリングアワードの受賞者です)は、これを彼の「10億ドルの間違い」として所有しています。Maybeタイプはこれを修正する唯一の方法ではありませんが、効果的な方法であることが証明されています。
たぶんファンクターとして
ある型を別の型に変換して、古い型の操作も新しい型で機能するように変換できるという考え方は、という便利なインスタンスFunctorをMaybe a持つHaskell型クラスの背後にある概念です。
Functorはと呼ばれるメソッドを提供fmapします。これは、基本型(などInteger)の値に及ぶ関数を、リフト型(などMaybe Integer)の値に及ぶ関数にマッピングします。値を処理fmapするために変換された関数は、次のように機能しますMaybe。
case maybeVal of
Nothing -> Nothing -- there is nothing, so just return Nothing
Just val -> Just (f val) -- there is a value, so apply the function to it
したがって、Maybe Integer値m_xとInt -> Int関数がある場合、実際に値を取得するかどうかを心配することなく、関数をに直接適用fできます。実際、リフトされた関数のチェーン全体を値に適用でき、終了時に明示的に1回だけチェックすることを心配するだけで済みます。fmap f m_xfMaybe IntegerInteger -> IntegerMaybe IntegerNothing
たぶんモナドとして
の概念にMonadまだ慣れているかはわかりませんが、少なくともIO a以前に使用したことがあり、型シグネチャIO aはと非常によく似ていMaybe aます。けれどもIO、それはあなたにそのコンストラクタを公開していないので、唯一のHaskellのランタイムシステムによって、「走る」ことができるという点で特別で、それもまだだFunctorことに加えてMonad。実際、a MonadはFunctorいくつかの追加機能を備えた特別な種類であるという重要な意味がありますが、これはそのための場所ではありません。
とにかく、のようなモナドIO「値の計算その結果」を表す新しいタイプのマップタイプと、あなたはに機能を持ち上げることができるMonad非常に介して、タイプfmapと呼ばれる様機能 liftM値の結果が評価したことを「計算になり、通常の関数であること関数。"
その(あなたがこれまでのところを読んでいる場合)あなたはおそらく推測しているMaybeにもありますMonad。「値を返せない可能性のある計算」を表します。fmap例と同様に、これにより、各ステップの後にエラーを明示的にチェックする必要なく、一連の計算を行うことができます。そして実際、Monadインスタンスの構築方法では、に遭遇するとすぐにMaybe値の計算が停止するNothingため、計算の途中での即時の中止や値のない戻りのようなものです。
あなたは多分書いたかもしれない
前に言ったようにMaybe、言語構文やランタイムシステムに組み込まれている型には固有のものはありません。Haskellがデフォルトで提供していない場合は、自分ですべての機能を提供できます。実際、とにかく自分でもう一度名前を変えて書いて、同じ機能を得ることができます。
うまくいけば、Maybeタイプとそのコンストラクターを理解できたと思いますが、それでも不明な点がある場合は、お知らせください!
Maybeは他の言語が使用する場所nullやnil(いたるところにひどい言葉がNullPointerException潜んでいる)場所をよく使用することを述べておく必要があります。現在、他の言語もこの構造を使用し始めています。ScalaasOption、さらにはJava 8でもOptional型が使用されます。