3

私はこのタイプとこれらの機能を持っています:

data Tag a where
    Tag :: (Show a, Eq a, Ord a, Storable a, Binary a) => a -> BL.ByteString -> Tag a

getVal :: Tag a -> a
getVal (Tag v _) = v

isBigger :: Tag a -> Tag a -> Bool
a `isBigger` b = (getVal a) > (getVal b)

コードは型チェックを行いません:

No instance for (Ord a)
  arising from a use of `>'
In the expression: (getVal a) > (getVal b)
In an equation for `isBigger':
    a isBigger b = (getVal a) > (getVal b)

 

しかし、なぜそうしないのか理解できません。Tag aにはコンテキストがあり(Show a, Eq a, Ord a, Storable a, Binary a)getVaこのコンテキストを保持する必要があります。私のやり方が間違っているのでしょうか、それとも GADTs 拡張機能の制限ですか?

これは機能します:

isBigger :: Tag a -> Tag a -> Bool
(Tag a _) `isBigger` (Tag b _) = a > b

編集:例を最小限の例に変更しました

編集: わかりました、なぜこのタイプチェックをしないのですか?

isBigger :: Tag a -> Tag a -> Bool
isBigger ta tb =
    let (Tag a _) = ta
        (Tag b _) = tb
    in
        a > b
4

1 に答える 1

6

の型シグネチャgetValが正しくありません。型が必要です

 getVal (Storable a, Ord a, ...) => Tag a -> a
 getVal (Tag v _) = v

これが推測されない理由は、次のようなことができるからです。

 doh :: Tag a
 doh = undefined

これでa、制約はなくなりました。次のようなことができます

 getVal (doh :: Tag (IO Int)) == getVal (doh :: Tag (IO Int))

getValそれらの制約があった場合。

の唯一の非ボトムインスタンスにTagは型クラスの制約がありますが、これはタイプチェッカーにとって十分ではありません。


新しい質問に答えるために

このような型を分解すると

 foo tag = let (Tag a _) = tag
               (Tag b _) = tag
           in a > b

GHC はそれらを適切に統合しません。aこれは、パターン マッチに到達するまでにタイプチェッカーが の型をすでに決定しているためだと思われますが、トップ レベルのマッチでは適切に統合されます。

 foo (Tag a _) (Tag b _) = a > b
于 2013-09-05T16:50:03.500 に答える