Haskell型クラスを使用して可換性を強制する


11

一緒に交差できる幾何オブジェクトの型クラスを定義したい:

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

アイデアは、さまざまなタイプのオブジェクトを処理できる汎用の交差関数を持つことです。次のようなインスタンスを想像できます

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

しかし、交差点が可換であることも宣言したいと思います。

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

問題は、私は評価するたびにすることであるintersect x y最初のフォームのインスタンス定義せずにIntersect a b caのタイプであるxbの一種であるがyプログラムが無限ループに入り、おそらく可換性について再帰インスタンス宣言によって引き起こされます。理想的にintersect Egg Baconは、そのようなインスタンスが定義されておらず、無限ループに陥るのではなく、タイプチェックに失敗するようなものが必要です。これを実装するにはどうすればよいですか?


タイプファミリを使用して実行できることのように思えます。スタックオーバーフローでより良い応答が得られる場合があります。
ベンジャミンホジソン

2
ここでは可換性を強制モナドについてのブログ記事があり、多分それは助けることができる:gelisam.blogspot.ca/2013/07/the-commutative-monad.html
ダニエル・ディアスCarrete

回答:


2

まず、可換パッケージを使用できます。この場合intersect、次のように型シグネチャを変更しますが、それ以外の場合、残りのコードは「正常に機能します」。

instersect :: Commutative a b -> c

ただし、タイプクラスのすべてのインスタンスでプロパティテストを実行して、実際に通勤できることを確認するために、hspecでQuickCheckを使用することもできます。これによりオーバーヘッドが削減される可能性があります-私は頭の外ではわからないので、ベンチマークを行う必要があります。例えば:

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)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.