Tại sao loại ghci desugar lại liệt kê và loại họ? Điều này có thể bị vô hiệu hóa có chọn lọc không?


93

Tôi đang cố gắng làm cho các loại ghci hiển thị cho thư viện của mình trực quan nhất có thể, nhưng tôi đang gặp rất nhiều khó khăn khi sử dụng các tính năng loại nâng cao hơn.

Giả sử tôi có mã này trong một tệp:

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}

import GHC.TypeLits

data Container (xs::[*]) = Container

Tôi tải nó lên bằng ghci, sau đó tôi gõ lệnh sau:

ghci> :t undefined :: Container '[String,String,String,String,String]

Thật không may, ghci cho tôi cái nhìn khá xấu xí:

:: Container
       ((':)
          *
          String
          ((':)
             * String ((':) * String ((':) * String ((':) * String ('[] *))))))

ghci đã loại bỏ đường cho các chuỗi cấp loại. Có cách nào để ngăn ghci làm điều này và chỉ cho tôi phiên bản đẹp không?


Trên một ghi chú liên quan, giả sử tôi tạo một Replicatehàm cấp loại

data Nat1 = Zero | Succ Nat1

type family Replicate (n::Nat1) x :: [*]
type instance Replicate Zero x = '[]
type instance Replicate (Succ n) x = x ': (Replicate n x)

type LotsOfStrings = Replicate (Succ (Succ (Succ (Succ (Succ Zero))))) String

Bây giờ, khi tôi hỏi ghci cho một loại sử dụng LotsOfStrings:

ghci> :t undefined :: Container LotsOfStrings

ghci rất tốt và cho tôi kết quả khá:

undefined :: Container LotsOfStrings

Nhưng nếu tôi yêu cầu Replicatephiên bản d,

ghci> :t undefined :: Container (Replicate (Succ (Succ (Succ (Succ (Succ Zero))))) String)

ghci thay thế cho họ kiểu khi nó không làm điều đó cho từ đồng nghĩa kiểu:

:: Container
       ((':)
          *
          [Char]
          ((':)
             * [Char] ((':) * [Char] ((':) * [Char] ((':) * [Char] ('[] *))))))

Tại sao ghci thực hiện thay thế cho họ kiểu, mà không phải là từ đồng nghĩa kiểu? Có cách nào để kiểm soát khi nào ghci sẽ thay thế?


7
Bởi vì từ đồng nghĩa kiểu được thiết kế hoàn toàn cho con người - nó không thay thế vì nó thừa nhận rằng bạn đã tạo từ đồng nghĩa kiểu vì bạn muốn viết / xem kiểu theo cách đó. Nó thực hiện thay thế với họ kiểu vì họ kiểu thực sự là để tính toán / suy luận một kiểu chứ không phải hiển thị nó.
AndrewC

Giải pháp cho vấn đề của bạn nằm trong câu hỏi của bạn - hãy tạo một loại từ đồng nghĩa nếu bạn muốn viết tắt.
AndrewC

2
@AndrewC Tôi vừa nghĩ ra một câu hỏi khác liên quan đến nhận xét của bạn: Tại sao các loại Chuỗi đôi khi được hiển thị [Char]và đôi khi được hiển thị dưới dạng String?
Mike Izbicki

1
Tôi nghĩ ghci cố gắng duy trì loại từ đồng nghĩa mà nó tìm thấy trong nguồn. Nghĩa là, nếu một hàm được khai báo là kiểu String->String, thì kiểu kết quả của nó sẽ được hiển thị dưới dạng String. Tuy nhiên, nếu nó phải xây dựng một kiểu từ các mảnh, chẳng hạn như "abc"(giống như 'a':'b':'c':[]) thì không có từ đồng nghĩa nào để bảo toàn. Đây là suy đoán thuần túy.
n. 'đại từ' m.

4
@nm: Lưu ý rằng GHC thực hiện một nỗ lực tương tự để bảo toàn tên của các biến kiểu, khi các kiểu suy ra chung chung hơn thống nhất với các biến kiểu ít chung chung hơn, được đặt tên rõ ràng. Tôi nghi ngờ rằng nếu kiểu rõ ràng Stringđược hợp nhất với các biến kiểu f ahoặc [a], nó sẽ được hiển thị như [Char]sau vì những lý do tương tự.
CA McCann

Câu trả lời:


2

Cách giải quyết mà tôi biết là sử dụng: kind. Ví dụ,

ghci>: kind (Vùng chứa '[Chuỗi, Chuỗi, Chuỗi, Chuỗi, Chuỗi])

Cung cấp:

(Vùng chứa '[Chuỗi, Chuỗi, Chuỗi, Chuỗi, Chuỗi]) :: *

Trong khi

ghci>: loại! (Vùng chứa '[Chuỗi, Chuỗi, Chuỗi, Chuỗi, Chuỗi])

Sẽ in một cái gì đó như thế này:

Thùng đựng hàng

((':)

  *
  [Char]
  ((':)
     * [Char] ((':) * [Char] ((':) * [Char] ((':) * [Char] ('[] *))))))

Tất nhiên, về mặt chính thức, bạn đang hỏi ghci một câu hỏi khác kind, nhưng nó hoạt động. undefined ::Dù sao thì việc sử dụng cũng là một cách giải quyết, vì vậy tôi nghĩ điều này có thể đủ.


Tôi chỉ sử dụng undefined ::để đưa ra một ví dụ dễ hiểu. Vấn đề thực sự là khi bạn nhận được một thông báo lỗi có một loại danh sách một nghìn loại khác nhau. Cần nhiều trang để in ra và rất khó phân tích cú pháp.
Mike Izbicki

Vâng, đủ công bằng. Có thể đã nhận ra điều đó. Tôi nợ bạn một câu trả lời tốt hơn
user2141650

2

Điều này được khắc phục trong GHC 7.8 sắp tới.

GHC 7.6 in các loại nếu một kiểu dữ liệu sử dụng PolyKinds. Vì vậy, bạn thấy (':) * String ('[] *)thay vì chỉ (':) String '[].

Trong GHC 7.8, các loại không còn được hiển thị theo mặc định và kiểu dữ liệu của bạn được in khá đẹp dưới dạng danh sách, như bạn mong đợi. Bạn có thể sử dụng cờ mới -fprint-explicit-kindsđể xem các loại rõ ràng như trong GHC 7.6. Tôi không biết lý do cho điều này, có lẽ các loại rõ ràng được dùng để hỗ trợ cho việc hiểu PolyKinds.


0
import GHC.TypeLits

data Container (xs::[*]) = Container

Tôi tải nó lên bằng ghci, sau đó tôi gõ lệnh sau:

:t undefined :: Container '[String,String,String,String,String]

Vì thế...? Tôi cho rằng bạn vẫn nhận được kết quả sau khi tôi giải quyết vấn đề String ((':) * String ((':) * String ((':) * ....
bùng binh trái
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.