Sử dụng các lớp loại Haskell để thực thi giao hoán


11

Tôi muốn định nghĩa một lớp loại cho các đối tượng hình học có thể được giao nhau:

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

Ý tưởng là để có một chức năng giao cắt mục đích chung có thể xử lý các đối tượng thuộc các loại khác nhau. Người ta có thể tưởng tượng những trường hợp như

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

Nhưng tôi cũng muốn tuyên bố rằng giao lộ là giao hoán:

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

Vấn đề là bất cứ khi nào tôi đánh giá intersect x ymà không xác định trước một thể hiện của biểu mẫu Intersect a b c, đâu alà loại xblà loại y, chương trình sẽ đi vào một vòng lặp vô hạn , có lẽ là do khai báo thể hiện đệ quy về giao hoán. Lý tưởng nhất là tôi muốn một cái gì đó intersect Egg Baconkhông thể kiểm tra kiểu vì không có trường hợp nào được xác định, không bẫy tôi trong một vòng lặp vô hạn. Làm thế nào tôi có thể thực hiện điều này?


Âm thanh giống như một cái gì đó bạn có thể cố gắng làm bằng cách sử dụng các loại gia đình. Bạn có thể nhận được phản hồi tốt hơn khi tràn stack.
Benjamin Hodgson

2
Đây là một bài đăng trên blog về một đơn vị thực thi giao hoán, có thể nó có thể giúp: gelisam.blogspot.ca/2013/07/the-commutative-monad.html
Daniel Díaz Carittle 25/1/2015

Câu trả lời:


2

Trước tiên, bạn có thể sử dụng gói giao hoán , trong trường hợp đó bạn sẽ sửa đổi chữ ký loại intersectthành sau, nhưng nếu không, phần còn lại của mã của bạn sẽ "chỉ hoạt động":

instersect :: Commutative a b -> c

Tuy nhiên, bạn cũng có thể sử dụng QuickCheck với hspec để chạy thử nghiệm thuộc tính trên tất cả các phiên bản của kiểu chữ của bạn để đảm bảo rằng nó thực sự đi lại. Điều này có thể làm giảm chi phí - bạn phải làm điểm chuẩn vì tôi không biết trên đỉnh đầu. Ví dụ:

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)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.