Nhập vai trò và hành vi gây nhầm lẫn bởi `coced`


11

Tôi có một loại Id avà tôi đang cố gắng ngăn chặn vô tình ép buộc, ví dụ: an Id Doubleto an Id Int.

Nếu tôi hiểu chính xác các loại vai trò, sau đây không nên biên dịch.

{-# LANGUAGE RoleAnnotations #-}
import Data.Coerce (coerce)

type role Id nominal
newtype Id a = Id String

badKey :: Id Int
badKey = coerce (Id "I point to a Double" :: Id Double)

Thật không may, nó không:

Prelude> :load Id.hs
[1 of 1] Compiling Main             ( Id.hs, interpreted )
Ok, one module loaded.
*Main> :type badKey
badKey :: Id Int

Tôi còn thiếu gì về vai trò loại?


atrong Idlà một biến ảo và không có tác động đến giá trị thực bên trong. Nếu bạn có newtype Id a = Id a, thì sự ép buộc sẽ thất bại.
lehins

@lehins Quan điểm của việc type rolelàm cho điều đó không phải là trường hợp. Câu hỏi này là hỏi tại sao điều đó không làm việc.
Joseph Sible-Phục hồi Monica

Câu trả lời:


12

Coerciblecó ba "loại" trường hợp có thể (được trình biên dịch tự động tạo ra, không được xác định bởi người dùng). Chỉ một trong số họ thực sự bị ảnh hưởng bởi vai trò .

  • Mỗi loại là cưỡng chế với chính nó.
  • Bạn có thể ép buộc "bên dưới" một hàm tạo kiểu, với điều kiện các biến loại bị ảnh hưởng là representationalhoặc phantom. Ví dụ, bạn có thể ép buộc Map Char Inta Map Char (Data.Monoid.Sum Int)Mapchúng tôi có type role Map nominal representational.
  • Bạn luôn có thể ép buộc một kiểu mới cho kiểu cơ bản và ngược lại, với điều kiện hàm tạo kiểu mới nằm trong phạm vi. Điều này bỏ qua tất cả các vai trò! Lý do là, do nhà xây dựng đã có sẵn, bạn luôn có thể bọc và tháo gỡ thủ công, vì vậy vai trò này không mang lại cho bạn sự an toàn nào.

Trong ví dụ của bạn, quy tắc thứ ba được áp dụng. Nếu kiểu mới được định nghĩa trong một mô-đun khác và hàm tạo không được nhập, việc ép buộc sẽ thất bại (để làm cho nó hoạt động trở lại, bạn sẽ cần phải chuyển vai trò sang phantom).

Các hành vi đặc biệt hơi ngạc nhiên cho newtypes được giải thích trong này vấn đề GHC.

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.