Làm thế nào để chứng minh loại bình đẳng quy nạp mà không có lớp?


8

Tôi đang cố gắng chứng minh tính kết hợp của các danh sách cấp độ theo cách cho phép tôi chuyển đổi giữa các loại tương đương mà không mang theo bất kỳ ràng buộc nào.

Giả sử định nghĩa chuẩn của phép nối:

type family (++) (xs :: [k]) (ys :: [k]) :: [k] where
  '[] ++ ys = ys
  (x ': xs) ++ ys = x ': (xs ++ ys)

Giả sử, tôi được cung cấp một chức năng:

given :: forall k (a :: [k]) (b :: [k]) (c :: [k]). Proxy ((a ++ b) ++ c)
given = Proxy  -- Proxy is just an example

và tôi muốn gọi hàm này và sau đó sử dụng tính kết hợp:

my :: forall k (a :: [k]) (b :: [k]) (c :: [k]). Proxy (a ++ (b ++ c))
my = given @k @a @b @c  -- Couldn't match type ‘(a ++ b) ++ c’ with ‘a ++ (b ++ c)’

Loại bình đẳng này thực sự không tầm thường, vì vậy không có gì ngạc nhiên khi trình biên dịch không hiểu nó, tuy nhiên tôi có thể chứng minh điều đó! Thật không may, tôi không biết làm thế nào để thuyết phục trình biên dịch mà tôi có thể.

Suy nghĩ đầu tiên tự nhiên của tôi là làm một cái gì đó như:

proof :: forall k (a :: [k]) (b :: [k]) (c :: [k]). (a ++ (b ++ c)) :~: ((a ++ b) ++ c)
proof = _

và sau đó thay đổi chức năng của tôi thành:

my :: forall k (a :: [k]) (b :: [k]) (c :: [k]). Proxy (a ++ (b ++ c))
my = case proof @k @a @b @c of Refl -> given @k @a @b @c

Nhưng tôi vẫn phải xác định proofvà đối với điều này, tôi cần thực hiện cảm ứng trên các đối số kiểu của nó. Cách duy nhất để thực hiện cảm ứng đối với các loại trong Haskell mà tôi biết là xác định một loại loại, nhưng sau đó tôi sẽ phải thêm các ràng buộc tương ứng cho loại mymà tôi không muốn làm - thực tế là nó gọi givenvà ép buộc kết quả là một chi tiết triển khai trên YouTube.

Có cách nào để chứng minh loại bình đẳng này trong Haskell mà không dùng đến các định đề không an toàn không?


1
Đây sẽ là trường hợp sử dụng cho các loại phụ thuộc, nhưng Haskell không có các loại đó. Chúng ta cần phải dùng đến singletons (để chúng ta có thể khớp mẫu và lặp lại), có thể thông qua các lớp loại. Tôi không nghĩ rằng bạn có thể viết một thuật ngữ không thuộc loại dưới cùng (a++(b++c)) :~: ((a++b)++c)mà không cần thêm các đối số đơn lẻ hoặc các ràng buộc kiểu chữ.
chi

Câu trả lời:


6

Không, bạn không thể chứng minh điều này mà không có ràng buộc kiểu chữ, bởi vì nó không đúng. Cụ thể, đây là một ví dụ:

Any ++ ([] ++ []) -- reduces to Any ++ []
(Any ++ []) ++ [] -- does not reduce

Để loại trừ sự tồn tại (ngu ngốc) của Any, bạn phải sử dụng một kiểu chữ không có Anyphiên bản; không còn lựa chọn nào khác.


Ah, phải, tôi tiếp tục lãng quên về Any:( Tôi đã hy vọng rằng các chú thích loại trong định nghĩa của tôi về. ++Sẽ đảm bảo đó là sự thật, nhưng Anyrõ ràng vi phạm này.
kirelagin

1
AnyVề cơ bản không chỉ là undefinedở cấp độ loại? Vì nó đúng về mặt đạo đức để giả vờ cái sau không tồn tại, tại sao chúng ta không thể làm như vậy cho cái trước?
Joseph Sible-Phục hồi lại

4
@ JosephSible-RebstateMonica Chắc chắn, chúng tôi có thể giả vờ tất cả những gì bạn thích. Và sau đó, cách bạn chuyển đổi giả vờ cấp độ loại của bạn sang cấp độ tính toán là sử dụng unsafeCoerce. Nhưng câu hỏi rõ ràng yêu cầu tránh unsafeCoerce, và vì vậy chúng tôi không thể giả vờ sau tất cả.
Daniel Wagner
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.