Haskell: YesNo 型クラス。なぜ Integer なのか? 質問する

Haskell: YesNo 型クラス。なぜ Integer なのか? 質問する

GHCi が整数の型をどのように想定するかについて質問があります。

私はLearn you a HaskellのYes-No型クラスを読んでいました。

全文を読みたい方は、こちらをクリックしてください。http://learnyouahaskell.com/making-our-own-types-and-typeclasses#a-yes-no-typeclass

簡単に言うと、この章では、独自のクラスを定義することで、多くの型で動作する関数を作成できることを示します。

この本では関数を持つYesNoクラスを定義しています

yesno :: a -> Bool

IntYesNoクラスのインスタンスとして作成する

instance YesNo Int where
    yesno 0 = False
    yesno _ = True

これをGHCiにロードして入力すると

yesno 0

Intエラーが返されました。おそらく、GHCi は 0 がクラス内のor またはIntegerorDoubleまたはその他の型であるかどうかを判断できないためだと思いましたNum。実際には、yesno (0::Int) と入力すると機能しました。

それで、楽しみのためにクラスIntegerのインスタンスを作成し、YesNo

instance YesNo Integer where
    yesno 0 = True
    yesno _ = False

(TrueとFalseを逆にしたことに注意してください)そして再び、

yesno 0

(型宣言なし) の場合、GHCi は と表示しましたTrue

さらに、私が入力したとき

yesno $ fromIntegral 0

を返しましたTrue。これは、GHCi が の型をfromIntegral 0であると認識していることを意味しますInteger

ということは、GHCiで整数を入力すると、通常はその値がIntegerではなく であると想定されるということですか?:t 0返されるので混乱しています。Num a => a

ベストアンサー1

タイプです債務不履行ghci の拡張デフォルト ルールと一緒に使用します。

整数リテラルは多態的であり、 型を持ちますNum a => a( を表すためfromInteger literal)。ただし、式を評価する場合 (たとえば、結果を印刷する必要がある場合)、式には単態型を指定する必要があります。

それ自体では、

yesno 0

は、と というNum a2つの制約を に課し、式全体は曖昧な型を持つことになる。YesNo a0

yesno 0 :: (Num a, YesNo a) => Bool

(制約内の型変数は の右側の型から到達できないため、あいまいです=>)。

一般的に、あいまいな型は型エラーですが、制約された型変数をデフォルト型でインスタンス化することであいまいさが解決される場合もあります。言語仕様の規則では、型変数はデフォルトにすることができます。

あいまいな型が発見された場合、あいまいな型変数はv次の場合にデフォルト設定可能です。

- `v` appears only in constraints of the form `C v`, where `C` is a class, and
- at least one of these classes is a numeric class, (that is, `Num` or a subclass of `Num`), and
- all of these classes are defined in the Prelude or a standard library (Figures 6.2–6.3 show the numeric classes, and Figure 6.1 shows the classes defined in the Prelude.)

この制約は(Num a, YesNo a)最初の 2 つの要件を満たしていますが、3 番目の要件は満たしていません。したがって、言語標準では、デフォルト設定はできず、型エラーになるはずです。

ただし、ghci は拡張されたデフォルト ルールを使用し、Prelude または標準ライブラリで定義されていないクラスによって制約される型変数もデフォルトにします。

明示的なデフォルト宣言がスコープ内にない限り、ここで制約のデフォルトが選択されます。Numデフォルトは でありInteger、 がInteger制約を満たしていない場合は がDouble試されます。

したがって、 がある場合instance YesNo Integer、ghci は型変数aを にデフォルト設定できますInteger。ただし、そのようなインスタンスが利用できない場合は、デフォルト候補のいずれにもインスタンスがないため、デフォルト設定は失敗します。

おすすめ記事