2011-08-26 15 views
27

いくつかのリングが標準機能を装備することができ、例えばヘッドより小さくなることはありませんしかし、私はこれを示す方法がわかりません。私はHaskellの制約は

instance (EuclideanDomain a, Eq a) => Ord a where 

を実行しようとしましたが、これは私にいくつかの警告を与え、そして私は、関連するコンパイラフラグを有効にすると、それは「制約がインスタンスヘッドより小さくなることはありません」私に指示 - 私はUndecidableInstancesを有効にした場合、すべてが地獄に行きます。

私がしたいことをする方法はありますか?

答えて

23

無限ループを避けるために、コンパイラは、通常、インスタンスの制約がインスタンス自体よりも「小さく」あることを要求し、アルゴリズムが終了するようにします。あなたのインスタンスはaを制約内で小さくしないので、コンパイラが不平を言っています。

拡張子がUndecidableInstancesの場合、この制限が解除され、終了することが証明されます。したがって、この拡張機能を使用する場合、コンパイラを無限ループに送ることができます。

これに対する一般的な解決策は、newtypeを追加することです:

newtype ByNorm a = ByNorm a 

instance (EuclideanDomain a, Eq a) => Ord (ByNorm a) where 
    compare (ByNorm x) (ByNorm y) = compare (norm x) (norm y) 

今、彼らはnewtypeを取り除くような制約は、インスタンスのヘッドよりも小さいです。延長は必要ありません。

+1

制約が小さくなるとはどういう意味ですか?確かに「EuclideanDomain a'sの数は少なく、 'a'sですか? – Xodarap

+4

@ Xodarap:「より少ないタイプのコンストラクタでラップされる」ように小さくなります。「このタイプの値がより少なくなります」ではなく – hammar

+0

私は参照してください。 'f :: EuclideanDomain a => a - > Ordering'を実行すると、' f x = compare x x'はコンパイルされません。私は何が欠けていますか? – Xodarap

27

ハマールはすでに解決策を提供しています。この例の別の問題を指摘したいと思います。あなたが表現したいのは、「タイプがEqEuclideanDomainのインスタンスであるときはいつでも、このルールを使用してOrdのインスタンスを作成します。しかし、これはハスケルでは表現できません。ライン

instance (EuclideanDomain a, Eq a) => Ord a where 

は実際には「あらゆるタイプのOrdインスタンスを作るために、このルールを使用してください。EuclideanDomainEqのインスタンスがスコープにない場合にはエラーだ」、を意味します。このルールは他のすべてのOrdインスタンスと重複するため、これはうまくありません。

基本的に、インスタンスClass typevarを書きたい場合は、newtypeが必要になります。

+1

ありがとう!これにより、問題の内容がより明確になります。 – Xodarap