1. ホーム
  2. haskell

[解決済み] Haskellの "Just "構文とは?

2022-05-26 16:55:38

質問

このキーワードが何をするのかについて、実際の説明を求めてインターネットを探し回りました。私が見たすべての Haskell のチュートリアルは、それをランダムに使用し始めるだけで、それが何をするのか説明しません (そして、私は多くのものを見てきました)。

の基本的なコードの一部です。 実世界の Haskell の基本的なコードです。 Just . このコードが何をするかは理解していますが Just が何なのかがわかりません。

lend amount balance = let reserve    = 100
                      newBalance = balance - amount
                  in if balance < reserve
                     then Nothing
                     else Just newBalance

私が観察したところでは、これは Maybe のタイピングに関連するものですが、私が学ぶことができたのはほとんどこれだけです。

の良い説明は Just が何を意味するのかをきちんと説明していただけると、とてもありがたいです。

どのように解決するのですか?

これは、実は通常のデータコンストラクタで、たまたま 前奏曲 これはすべてのモジュールに自動的にインポートされる標準ライブラリです。

Maybeとは何か、構造的に

定義は以下のような感じです。

data Maybe a = Just a
             | Nothing

その宣言は型を定義します。 Maybe a という型を定義しており,この型は型変数 a の代わりにどんな型でも使えるということです。 a .

構築と破壊

この型には2つのコンストラクタがあります。 Just aNothing . 型に複数のコンストラクタがある場合、その型の値は可能なコンストラクタのうちの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の意味するところ

多分、あなたはこれがどのように機能するか既に知っていたでしょう; 実際にどんな魔法もなく Maybe 値には何の魔法もありません。これは通常の Haskell Algebraic Data Type (ADT) に過ぎません。しかし、これは非常によく使われています。 Integer のような型を、余分な値を持つ新しいコンテキストに効果的に "lifting"または拡張するため、かなり使用されます ( Nothing を持つことになります。型システムによって Integer という があります。これによって、驚くほど多くのバグを防ぐことができます。

今日、多くの言語がこの種の無価値な値を NULL 参照によって扱っています。著名なコンピューター科学者である Tony Hoare (彼はクイックソートを発明し、チューリング賞を受賞しています) は、このことを自分のものとして認めています。 10 億ドルの間違いです。 . Maybe 型はこれを修正する唯一の方法というわけではありませんが、効果的な方法であることが証明されています。

ファンクタとしてのMaybe

ある型を別の型に変換することで、古い型に対する操作が というHaskellの型クラスは、新しい型で動作するように変換されるという概念です。 Functor というハスケルの型クラスの概念です。 Maybe a には便利なインスタンスがあります。

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_xInt -> Int 関数 f を実行することができます。 fmap f m_x を適用すると f を直接 Maybe Integer を、実際に値を持っているかどうかを気にすることなく、直接呼び出すことができます。実際、一連の持ち上げられた Integer -> Integer 関数を Maybe Integer を明示的にチェックすることだけを心配すればよいのです。 Nothing を明示的にチェックすることだけを考えればよいのです。

モナドとしての可能性

という概念にどの程度馴染みがあるかは分かりませんが、このように Monad の概念にどれだけ精通しているかは分かりませんが、少なくともあなたは IO a を使ったことがあり、型名が IO a と驚くほど似ています。 Maybe a . しかし IO はコンストラクタを公開しないので Haskell ランタイムシステムによってのみ "run" できるという点で特殊ですが、これもやはり Functor であることに加えて Monad . 実際、このように Monad は単に特別な Functor であり、いくつかの特別な機能を備えていますが、ここはそのことに触れる場所ではありません。

とにかく、モナドのような IO のようなモナドは型を新しい型にマッピングし、その型は "値を返す計算を表し、関数を Monad 型に引き上げることができます。 fmap -という非常に似た関数を使って liftM と呼ばれる、通常の関数を "関数を評価した値になるような計算をする関数に変えます。

ここまで読んだ方は)おそらく推測していると思いますが Maybe はまた Monad . これは、"値を返すのに失敗する可能性のある計算"を表します。と同じように fmap の例と同様に、これによって、各ステップの後で明示的にエラーをチェックすることなく、たくさんの計算を行うことができます。そして実際 Monad のインスタンスが構築されているため Maybe の値 を停止する が発生すると同時に Nothing が発生するとすぐにを停止するので、計算の途中で即座にアボートするか、無価値なリターンを行うようなものです。

You Could Have Written Maybe

先程も言ったように、本来であれば Maybe 型には、言語の構文やランタイムシステムに組み込まれているものはありません。Haskell がデフォルトで提供していないのであれば、そのすべての機能を自分で提供することができます! 実際、別の名前でとにかくもう一度自分で書いて、同じ機能を手に入れることができます。

を理解していることを望みます。 Maybe 型とそのコンストラクタを理解できたと思いますが、まだ不明な点があれば教えてください!