Tôi có một loại chứng cho danh sách loại cấp,Bạn có an toàn khi sử dụng unsafeCoerce cho các số dư hợp lệ không?
data List xs where
Nil :: List '[]
Cons :: proxy x -> List xs -> List (x ': xs)
cũng như các tiện ích sau đây.
-- Type level append
type family xs ++ ys where
'[] ++ ys = ys
(x ': xs) ++ ys = x ': (xs ++ ys)
-- Value level append
append :: List xs -> List ys -> List (xs ++ ys)
append Nil ys = ys
append (Cons x xs) ys = Cons x (append xs ys)
-- Proof of associativity of (++)
assoc :: List xs -> proxy ys -> proxy' zs -> ((xs ++ ys) ++ zs) :~: (xs ++ (ys ++ zs))
assoc Nil _ _ = Refl
assoc (Cons _ xs) ys zs = case assoc xs ys zs of Refl -> Refl
Bây giờ, tôi có hai định nghĩa khác nhau nhưng tương đương với một chức năng ngược lại loại cấp,
-- The first version, O(n)
type Reverse xs = Rev '[] xs
type family Rev acc xs where
Rev acc '[] = acc
Rev acc (x ': xs) = Rev (x ': acc) xs
-- The second version, O(n²)
type family Reverse' xs where
Reverse' '[] = '[]
Reverse' (x ': xs) = Reverse' xs ++ '[x]
Đầu tiên là hiệu quả hơn, nhưng thứ hai là dễ dàng hơn để sử dụng khi chứng minh điều cần trình biên dịch , vì vậy nó sẽ là tốt đẹp để có một bằng chứng về sự tương đương. Để thực hiện việc này, tôi cần bằng chứng là Rev acc xs :~: Reverse' xs ++ acc
. Đây là những gì tôi nghĩ ra:
revAppend :: List acc -> List xs -> Rev acc xs :~: Reverse' xs ++ acc
revAppend _ Nil = Refl
revAppend acc (Cons x xs) =
case (revAppend (Cons x acc) xs, assoc (reverse' xs) (Cons x Nil) acc) of
(Refl, Refl) -> Refl
reverse' :: List xs -> List (Reverse' xs)
reverse' Nil = Nil
reverse' (Cons x xs) = append (reverse' xs) (Cons x Nil)
Thật không may, revAppend
là O (n³), hoàn toàn đánh bại mục đích của bài tập này. Tuy nhiên, chúng tôi có thể bỏ qua tất cả điều này và nhận được O (1) bằng cách sử dụng unsafeCoerce
:
revAppend :: Rev acc xs :~: Reverse' xs ++ acc
revAppend = unsafeCoerce Refl
Điều này có an toàn không? Điều gì về trường hợp chung? Ví dụ: nếu tôi có hai loại gia đình F :: k -> *
và G :: k -> *
và tôi biết rằng chúng tương đương nhau, có an toàn để xác định những điều sau không?
equal :: F a :~: G a
equal = unsafeCoerce Refl
'Phản hồi' và': ~: 'là gì? Có lẽ đó là nhân chứng của bạn về sự bình đẳng kiểu, giống như 'dữ liệu a: ~: b nơi Refl :: a: ~: a'? – Cirdec
@Cirdec Chính xác. Bạn có thể tìm thấy định nghĩa trong cơ sở (xem [Data.Type.Equality] (http://hackage.haskell.org/package/base-4.7.0.1/docs/Data-Type-Equality.html)) – YellPika
Được nâng thẳng từ [Blog của Richard Eisenberg] (https://typesandkinds.wordpress.com), nếu bạn biết bằng chứng của bạn chấm dứt và chỉ muốn GHC gõ kiểm tra chúng, bạn có thể thêm '{- # RULES 'revAppend" revAppend ... = unsafeCoerce Reflect # -} '.Không có chi phí thời gian chạy và bạn vẫn được kiểm tra bằng chứng - chỉ chấm dứt không được chọn. – Alec