xem xét định nghĩa đơn giản của một vector chiều dài-lập chỉ mục:Biểu diễn thời gian chạy đặc biệt của loại []?
data Nat = Z | S Nat
infixr 5 :>
data Vec (n :: Nat) a where
V0 :: Vec 'Z a
(:>) :: a -> Vec n a -> Vec ('S n) a
Đương nhiên tôi sẽ tại một số điểm cần các chức năng sau:
vec2list :: Vec n a -> [a]
Tuy nhiên, chức năng này thực sự chỉ là một bản sắc ưa thích. Tôi tin rằng các biểu diễn thời gian chạy của hai loại này giống nhau, vì vậy,
vec2list :: Vec n a -> [a]
vec2list = unsafeCoerce
sẽ hoạt động. Than ôi, nó không:
>vec2list ('a' :> 'b' :> 'c' :> V0)
""
Mọi đầu vào chỉ trả về danh sách trống. Vì vậy, tôi cho rằng sự hiểu biết của tôi là thiếu. Để kiểm tra nó, tôi xác định như sau:
data List a = Nil | Cons a (List a) deriving (Show)
vec2list' :: Vec n a -> List a
vec2list' = unsafeCoerce
test1 = vec2list' ('a' :> 'b' :> 'c' :> V0)
data SomeVec a = forall n . SomeVec (Vec n a)
list'2vec :: List a -> SomeVec a
list'2vec x = SomeVec (unsafeCoerce x)
Đáng ngạc nhiên là công trình này! Nó chắc chắn không phải là một vấn đề với GADT sau đó (suy nghĩ ban đầu của tôi).
Tôi nghĩ rằng loại List
thực sự giống hệt nhau khi chạy đến []
. Tôi cũng cố gắng thử nghiệm điều này:
list2list :: [a] -> List a
list2list = unsafeCoerce
test2 = list2list "abc"
và nó hoạt động! Dựa trên thực tế này, tôi phải kết luận rằng [a]
và List a
phải có cùng một biểu diễn thời gian chạy. Tuy nhiên, sau
list2list' :: List a -> [a]
list2list' = unsafeCoerce
test3 = list2list' (Cons 'a' (Cons 'b' (Cons 'c' Nil)))
không hoạt động. list2list'
lại luôn trả về danh sách trống. Tôi tin rằng "có biểu diễn thời gian chạy giống hệt nhau" phải là một mối quan hệ đối xứng, vì vậy điều này dường như không có ý nghĩa.
Tôi bắt đầu nghĩ rằng có thể có điều gì đó hài hước với các kiểu "nguyên thủy" - nhưng tôi luôn tin rằng []
chỉ là cú pháp đặc biệt, không phải ngữ nghĩa. Có vẻ như đó là trường hợp:
data Pair a b = Pair a b deriving (Show, Eq, Ord)
tup2pair :: (a,b) -> Pair a b
tup2pair = unsafeCoerce
pair2tup :: Pair a b -> (a,b)
pair2tup = unsafeCoerce
Các công trình chức năng đầu tiên và lần thứ hai không - giống như trong trường hợp của List
và []
. Mặc dù trong trường hợp này, pair2tup
segfaults như trái ngược với luôn luôn trả về danh sách trống.
Dường như là nhất quán không đối xứng đối với các loại sử dụng cú pháp "được tích hợp sẵn". Quay lại ví dụ Vec
, sau đây
list2vec :: [a] -> SomeVec a
list2vec x = SomeVec (unsafeCoerce x)
cũng hoạt động tốt! GADT thực sự không phải là đặc biệt.
Câu hỏi đặt ra là: cách trình bày thời gian chạy của các loại sử dụng cú pháp "dựng sẵn" khác với cú pháp không?
Cách khác, cách viết một lần ép buộc không có chi phí từ Vec n a
đến [a]
? Điều này không trả lời câu hỏi nhưng giải quyết được vấn đề.
Thử nghiệm được thực hiện với GHC 7.10.3.
Được ghi chú bởi người nhận xét, hành vi này chỉ xuất hiện khi diễn giải. Khi được biên dịch, tất cả các hàm hoạt động như mong đợi. Câu hỏi vẫn được áp dụng, chỉ để hiển thị thời gian chạy khi diễn giải.
"Hoạt động tốt" kết hợp với 'unsafeCoerce' giống như chỉ vào một đống đổ nát và nói" nhìn, nó vẫn đứng ". Nó giống như sử dụng 'reinterpret_cast (…)' trong C++. Với lý do chính xác, nó sẽ làm việc, nhưng mặt khác GHC không suy luận bất kỳ trường hợp 'Coercible' cho bất kỳ loại nào của bạn. Điều đó đang được nói, IIRC 'RuntimeRep' thay đổi trong GHC 8 (xem' GHC.Types') do [đa hình độ cao] (http://stackoverflow.com/q/35318562/1139697). –
Zeta
Để trả lời câu hỏi thứ hai của bạn: 'newtype Vec (n :: Nat) a = MkVec [a]' cùng với 'v0 :: Vec 'Z a; v0 = [] ',' (|>) :: a -> Vec n a -> Vec ('S n) a; (|>) x = ép buộc. (x :). coerce', trong đó 'coerce' là từ' Data.Coerce'. Trình biên dịch sau đó chính xác infers rằng 'n :: Nat' chỉ là một loại ma. – Zeta
@Zeta Như bạn đã nói, với lý do chính xác, nó sẽ hoạt động. Tôi không nghĩ rằng đây rõ ràng là một trong những cách sử dụng "được chấp thuận", nhưng trong thực tế, các biểu diễn thời gian chạy của các kiểu "đạo đức bình đẳng" là * thường * giống nhau, ngoại trừ trong các trường hợp trên. Câu hỏi này không phải là về thiết kế cấp cao của mã Haskell. Đó là về sự can đảm của GHC. Câu hỏi thay thế thực sự là một mẹo - tôi khá chắc chắn nó không thể không có 'unsafeCoerce' - nhưng tôi không muốn ngăn cản ai đó cố gắng chứng minh tôi sai. – user2407038