Değişebilirliği zorlamak için Haskell tipi sınıfları kullanma


11

Birbiriyle kesişen geometrik nesneler için bir tür sınıfı tanımlamak istiyorum:

class Intersect a b c | a b -> c where
  intersect :: a -> b -> c
-- Language extensions: -XMultiParamTypeClasses, -XFunctionalDependencies

Fikir, farklı tipteki nesneleri işleyebilen genel amaçlı bir kavşak fonksiyonuna sahip olmaktır. Birisi şöyle düşünebilirdi:

instance Intersect Line Plane (Maybe Point) where
  ...
instance Intersect Plane Plane (Maybe Line) where
  ...

Ama aynı zamanda kavşağın değişmeli olduğunu beyan etmek istiyorum:

instance (Intersect a b c) => Intersect b a c where
  intersect x y = intersect y x
-- Language extensions: -XUndecidableInstances

Sorun değerlendirilmesi her olmasıdır intersect x ybirinci biçiminin bir örneğini tanımlamadan Intersect a b c, atürüdür xve btürüdür y, program sonsuz döngüye girer muhtemelen komutatiflik ilgili özyinelemeli örneği beyan neden olduğu. İdeal olarak intersect Egg Baconböyle bir örnek tanımlanmadı, beni sonsuz bir döngüde tuzak değil çünkü tip-kontrol başarısız olmak istiyorum gibi bir şey istiyorum . Bunu nasıl uygulayabilirim?


Tip aileleri kullanarak yapmaya çalışabileceğiniz bir şey gibi geliyor. Yığın taşması durumunda daha iyi yanıt alabilirsiniz.
Benjamin Hodgson

2
İşte değişebilirliği zorlayan bir monad hakkında bir blog yazısı, belki de yardımcı olabilir: gelisam.blogspot.ca/2013/07/the-commutative-monad.html
Daniel Díaz Carrete

Yanıtlar:


2

İlk olarak, değişmeli paketi kullanabilirsiniz, bu durumda tür imzasını intersectaşağıdakilerle değiştirirsiniz, aksi takdirde kodunuzun geri kalanı "sadece işe yarar ":

instersect :: Commutative a b -> c

Ancak, aslında işe gidip gelmediğinden emin olmak için, tip sınıfınızın tüm örneklerinde bir özellik sınaması yapmak için QuickCheck'i hspec ile de kullanabilirsiniz. Bu yükü azaltabilir - kafamın üstünü bilmediğim için bir kıyaslama yapmanız gerekir. Örneğin:

import Test.Hspec

main :: IO ()
main = hspec $ do
    describe "intersect" $ do
        parallel $ it "should commute" $ do
            property $ \x y -> intersect x y == intersect (y :: Point) (x :: Line)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.