2013-12-16 24 views
6

Bu, Inconsistent Eq and Ord instances? numaralı sorudur.Haskell: Standart kütüphaneler, Eq ve Ord uyumlu olduğunu varsayıyor mu?

soru esasen vardır: Bir tür Eq ve Ord örneklerini bildirirken, kimse bu compare x y döner EQ sağlamalıdır ve ancak x == y döner True olur? Bu varsayımı bozan örnekler oluşturmak tehlikeli midir? Bir kişinin sahip olabileceği doğal bir yasa gibi görünüyor, ama Prelude'de açıkça belirtilmemiş gibi görünüyor. monad veya functor yasaları.

Temel cevap şuydu: Kütüphaneler bu kanunun sahip olduğunu varsayabilirler, çünkü bunu yapmak biraz tehlikelidir.

Sorum, şimdi, geçerli: standart kütüphaneler herhangi birini (özellikle Set veya Map) bu varsayımı yapmak? Sadece GHC ile birlikte verilen standart kütüphanelere güvenmekteyim diye, uyumsuz olan Eq ve Ord türlerine sahip olmak tehlikeli midir? (büyük-liste sorular hala kabul edilebilir olsaydı, soran olacaktır: Yaygın olarak kullanılan kütüphaneler bu yasayı varsayıyorum hangisi?)

Edit. Kullanım durumum orijinal soruna benzer. Özel bir örneğim var, Eq, biraz kullanıyorum. Ben Ord istediğim tek nedeni, onu bir Map etki alanı olarak kullanabilmem; Özel siparişi umursamıyorum ve bunu kesinlikle kodda kullanmaz. Yani, türetilmiş örneği Ord kullanabilirsem, o zaman hayatım daha kolay olacak ve benim kodum daha temiz olacak. (

class (Eq a) => Ord a where 
    ... 

Yani ihlali niteliğinde olacağı için

x == y   = compare x y == EQ 
    x /= y   = compare x y /= EQ 

ihlal etmek gibi yanlış olur:

+5

"hangi sıklıkla kullanılmış kütüphaneler bu kanunu kabul ediyorlar "--- insanların beyinleri? –

+0

Gerçekten de, daha iyi bir soru ((b) = (b == EQ ile karşılaştır) bir anlam ifade eder. – Ingo

+1

Bu sadece boş bir merak mıdır, yoksa ikisini değiştirmek için mantıklı olduğunu düşündüğünüz bir kullanım durumunuz var mı? Eğer ikincisiyse, sundugunu görmeyi çok isterim (cidden, şimdi merak ediyorum, ve iyi bir kullanım durumunun kendimi düşünemiyorum ....) – jamshidh

cevap

6

standard prelude içinde Ord kendisinin tanımı, bir Eq örneği olması zaten orada gerektirir Ord'daki bu işleçler için varsayılan tanımlardan).

x <= y   = compare x y /= GT 
    x < y   = compare x y == LT 
    x >= y   = compare x y /= LT 
    x > y   = compare x y == GT 

Düzenleme: Kullanım kütüphaneleri

standart kütüphaneler Ord 'ın == ve /= operatörlerin faydalanmak olmasaydı oldukça sürpriz olurdu. Belirli amaç operatörleri (==, /=, <=, <, >=, >) sık sık compare daha uygundur, bu yüzden onları map s veya filter s için kod kullanılan görmeyi beklersiniz.

see == being used in guards on keys in Data.Map in fromAscListWithKey. Bu özel fonksiyon sadece Eq sınıf sesleniyor ama anahtar da bir Ord bir örnek ise, Ord s ==Ord aynıdır sitesindeki compareEq olduğu bir varsayımdır elde edilen Map, diğer işlevler için kullanılacak ' compare ve EQ için test.

Bir kütüphane programcısı olarak, özel amaçlı işleçlerin herhangi biri, belirli bir amaç için compare'dan daha iyi performans gösterdiğinde şaşırmayacağım. Sonuçta, bu nedenle tüm Eq veya Ord örnekleri için polimorfik olarak tanımlanmak yerine Eq ve Ord sınıflarının bir parçasıdırlar. compare'un daha uygun olduğu durumlarda bile bunları kullanabileceğim bir noktaya gelebilirim. tanımlanmış olan işlem nasılsa kanonik ise örnekleri yalnızca yapılmalıdır typeclass, Cirdec cevabını uzatmak için

compareOp :: (Ord a) => Ordering -> Bool -> a -> a -> Bool 
compareOp EQ True = (==) 
compareOp EQ False = (/=) 
compareOp LT True = (<) 
compareOp LT False = (>=) 
compareOp GT True = (>) 
compareOp GT False = (<=) 
3

: Ben yaptım, muhtemelen böyle bir şey tanımlamak istiyorum. Makul bir Eq makul bir Ord uzatmazsa, o zaman diğer Eq ya da Ord tanımlamamak için en iyi yöntemdir. "Diğer" eşitlik için polimorf olmayan bir işlev yaratmak için yeterince kolaydır.

bu gerilimin büyük bir örnek seçilen yol örneğini oldu ne olduğundan bu durumda öteki "bariz" Monoid örneği

instance Monoid Int where 
    mzero = 1 
    mappend = (*) 

ile yarışmalar potansiyel Monoid örneği

instance Monoid Int where 
    mzero = 0 
    mappend = (+) 

olduğunu Birinin diğeri üzerinde "kanonik" olduğu net değil. Bu genellikle kullanıcının beklentisini en iyi şekilde karşılar ve hataları önler.

1

Bu ve orijinal soruya baştan sona kadar okuduktan, bu yüzden genel sorunu ele alacak ....

Sen bu-

Map BigThing OtherType 

ve bu-

(==)::BigThing->BigThing->Bool 
istiyorum

Bu durumlardan biri kesin olmak zorundadır, diğer durum performans nedenleriyle bazı verilerden yoksundur. (ilk soruda tam olarak olması gereken (==) idi, fakat bu sorudaki tersine hitap ediyor gibi görünüyorsun.

Örneğin, harita yalnızca

`name::BigThing->String` 

ama gibi bazı etikete göre sonucu depolamak istediğiniz (==) derin karşılaştırmak yapmalıdır. Bunu yapmanın bir yolu, uyumsuz compare ve (==) işlevlerini tanımlamak olacaktır. Ancak bu durumda, bu gereksizdir. Neden sadece yerine haritayı

Map String OtherThing 

kullanmak ve doğrudan çok büyük belge verilerine indeksine oldukça nadirdir bu-

lookup (name obj) theMap 

gibi bir arama yapmak ....

+0

Sadece kayıt için, eski soru aslında başka birinden geliyordu, ben değil (belki benim ifadelerim biraz belirsizdi) - ama benim durumum bu cevabın benim için de işe yaradığı kadar yakın, bu yüzden her durumda. – PLL