1

私はこのハスケルコードを持っています。Mord2 つのデータ型を作成したので、関数と型を比較できる新しいクラスを作成したいと考えていMlistます。

import Data.List

data Mlist a = Mlist [a]

data Mordering = MLT deriving (Eq, Show)

s = Mlist [1, 2, 3]
t = Mlist [1, 4, 2, 3]

class Mord a where 
    mcompare :: a -> a -> Mordering


instance Mord a => Mord (Mlist a) where
    mcompare (Mlist xs) (Mlist ys) = MLT

しかし、私がしようとすると、mcompare s t私は得ます

<interactive>:1:1:
    No instance for (Mord Integer)
      arising from a use of `mcompare'
    Possible fix: add an instance declaration for (Mord Integer)
    In the expression: mcompare s t
    In an equation for `it': it = mcompare s t

誰かが問題を見ていますか?

編集

ここに私の新しいコードがあります:

import Data.List

data Mlist a = Mlist [a]

data Mordering = MEQ | MIN deriving (Eq, Show)

s = Mlist [1, 2, 3]
t = Mlist [1, 4, 2, 3]

class Mord a where 
    mcompare :: a -> a -> Mordering

instance Mord (Mlist a) where
    mcompare (Mlist xs) (Mlist ys)
           | length xs == length ys && null (xs \\ ys) = MEQ
           | otherwise = MIN

しかし、私が今得るエラーは次のとおりです。

    No instance for (Eq a)
      arising from a use of `\\'
    In the first argument of `null', namely `(xs \\ ys)'
    In the second argument of `(&&)', namely `null (xs \\ ys)'
    In the expression: length xs == length ys && null (xs \\ ys)
Failed, modules loaded: none.
4

3 に答える 3

4

Haskellはこれを読みます:

instance Mord a => Mord (Mlist a) where
    mcompare (Mlist xs) (Mlist ys) = MLT

a「のインスタンスがあるすべての場合、のインスタンスMordもあります。ただし、のインスタンスがない場合は、のインスタンスもありません。申し訳ありませんが、もう一度たむろしましょう。いつか!」MordMlist aMordaMordMlist a

Mord aインスタンス宣言の一部はコンテキストと呼ばれます。これについて詳しくは、 A Gentle IntroductiontoHaskellをご覧ください。

インスタンスコンテキストは、コードなどの型コンストラクターで役立ち[]ますMlist。たとえば、標準Eqクラスとそのインスタンスを確認できます[a]

instance (Eq a) => Eq [a] where
    []     == []     = True
    (x:xs) == (y:ys) = x == y && xs == ys
    _xs    == _ys    = False

このインスタンスはどういう意味ですか?2つの空のリストは同じです。空でない2つのリストは、ヘッドが等しく、テールが等しい場合に等しくなります。他の2つの空でないリストは等しくありません。空のリストと空でないリストは等しくありません。

前の段落の一部を太字にしました。これは、「インスタンスコンテキストが役立つのはなぜですか?」という質問に答えるのに役立つためです。リストの例では、リストの同等性の定義の一部はリストの構造に由来しますが、他の部分はその要素の同等性に基づいています。つまり、リストの要素が等しいかどうかを比較できない限り、リストが等しいかどうかを比較することはできません。

関数は、同等性を有意義に比較できない値の典型的な例です。では、関数のリストが等しいかどうかをどのように確認できますか?

ghci> (+1) == (*2)
<interactive>:6:6:
    No instance for (Eq (a0 -> a0))
      arising from a use of `=='
    Possible fix: add an instance declaration for (Eq (a0 -> a0))
    In the expression: (+ 1) == (* 2)
    In an equation for `it': it = (+ 1) == (* 2)

ghci> [(+4)] == [\x -> 2 * x / 3]
<interactive>:8:8:
    No instance for (Eq (a0 -> a0))
      arising from a use of `=='
    Possible fix: add an instance declaration for (Eq (a0 -> a0))
    In the expression: [(+ 4)] == [\ x -> 2 * x / 3]
    In an equation for `it': it = [(+ 4)] == [\ x -> 2 * x / 3]

したがって、コードを機能させるには、使用されていないインスタンスコンテキストを削除するか、適切な基になるインスタンスを提供する必要があります。

instance Mord Int where
    mcompare ... = ...

s :: Mlist Int
s = Mlist [1, 2, 3]
t :: Mlist Int
t = Mlist [1, 4, 2, 3]
于 2013-03-13T17:28:22.357 に答える
3
instance Mord a => Mord (Mlist a) where

ここで、Mlist aが のインスタンスであり、 が のインスタンスであるMord場合にのみ、aが のインスタンスであると言いましたMordIntegerは のインスタンスではないMordためMlist Integer、 も のインスタンスではありませんMord。インスタンスを定義するMord Integerと、コードが機能します。

あなたの編集への対応: 新しいコードは機能しません。これは、等しいかどう\\かを比較できる値のリスト (つまり、型クラスのインスタンスである型の値) でのみ機能するためEqです。インスタンスに制約がないEqため、すべてのタイプで機能するはずだと言っていますが、すべてのタイプで\\機能するわけではないため、それはできません。インスタンスに制約を追加するとEq(つまりinstance (Eq a) => Mord (Mlist a) ...)、問題が解決されます。

于 2013-03-13T15:38:35.180 に答える