Saya ingin mendefinisikan kelas tipe untuk objek geometris yang dapat disatukan:
class Intersect a b c | a b -> c where
intersect :: a -> b -> c
-- Language extensions: -XMultiParamTypeClasses, -XFunctionalDependencies
Idenya adalah memiliki fungsi persimpangan tujuan umum yang dapat menangani objek dari berbagai jenis. Orang bisa membayangkan contoh seperti itu
instance Intersect Line Plane (Maybe Point) where
...
instance Intersect Plane Plane (Maybe Line) where
...
Tetapi saya juga ingin menyatakan bahwa persimpangan adalah komutatif:
instance (Intersect a b c) => Intersect b a c where
intersect x y = intersect y x
-- Language extensions: -XUndecidableInstances
Masalahnya adalah bahwa setiap kali saya mengevaluasi intersect x y
tanpa terlebih dahulu mendefinisikan instance dari form Intersect a b c
, di mana a
adalah tipe x
dan b
tipe y
, program masuk ke loop tak terbatas , mungkin disebabkan oleh deklarasi instance rekursif tentang komutativitas. Idealnya saya ingin sesuatu seperti intersect Egg Bacon
gagal mengetik-periksa karena tidak ada contoh seperti itu didefinisikan, tidak menjebak saya dalam loop yang tak terbatas. Bagaimana saya bisa menerapkan ini?
sumber
Jawaban:
Pertama, Anda bisa menggunakan paket komutatif , dalam hal ini Anda akan memodifikasi tipe tanda tangan
intersect
untuk yang berikut ini, tetapi jika tidak, sisa kode Anda akan "berfungsi":Namun, Anda juga dapat menggunakan QuickCheck dengan hspec untuk menjalankan tes properti di semua instance dari typeclass Anda untuk memastikan bahwa itu sebenarnya bolak-balik. Ini dapat mengurangi overhead - Anda harus melakukan benchmark karena saya tidak tahu dari atas kepala saya. Misalnya:
sumber