Saya mencoba membuat jenis tampilan ghci untuk perpustakaan saya seintuitif mungkin, tetapi saya mengalami banyak kesulitan saat menggunakan fitur jenis yang lebih canggih.
Katakanlah saya memiliki kode ini dalam sebuah file:
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
import GHC.TypeLits
data Container (xs::[*]) = Container
Saya memuatnya di ghci, lalu saya mengetik perintah berikut:
ghci> :t undefined :: Container '[String,String,String,String,String]
Sayangnya, ghci memberi saya tampilan yang agak jelek:
:: Container
((':)
*
String
((':)
* String ((':) * String ((':) * String ((':) * String ('[] *))))))
ghci telah menghilangkan gula untuk string level tipe. Apakah ada cara untuk mencegah ghci melakukan ini dan memberi saya versi yang cantik?
Pada catatan terkait, katakanlah saya membuat Replicate
fungsi level tipe
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
Sekarang, ketika saya meminta ghci untuk suatu tipe menggunakan LotsOfStrings
:
ghci> :t undefined :: Container LotsOfStrings
ghci bagus dan memberi saya hasil yang bagus:
undefined :: Container LotsOfStrings
Tetapi jika saya meminta Replicate
versi d,
ghci> :t undefined :: Container (Replicate (Succ (Succ (Succ (Succ (Succ Zero))))) String)
ghci menggantikan tipe family ketika tidak melakukannya untuk sinonim tipe:
:: Container
((':)
*
[Char]
((':)
* [Char] ((':) * [Char] ((':) * [Char] ((':) * [Char] ('[] *))))))
Mengapa ghci melakukan substitusi untuk keluarga tipe, tetapi bukan sinonim tipe? Apakah ada cara untuk mengontrol kapan ghci akan melakukan substitusi?
[Char]
dan terkadang ditampilkan sebagaiString
?String->String
, maka tipe hasilnya akan ditampilkan sebagaiString
. Namun jika itu harus membangun tipe dari potongan, seperti misalnya"abc"
(yang sama dengan'a':'b':'c':[]
) tidak ada sinonim untuk dipertahankan. Ini murni spekulasi.String
disatukan dengan variabel tipef a
atau[a]
, itu akan ditampilkan[Char]
setelahnya karena alasan yang sama.Jawaban:
Solusi yang saya tahu adalah menggunakan: jenis. Misalnya,
Memberikan:
Sementara
Akan mencetak sesuatu seperti ini:
Secara resmi, tentu saja, Anda menanyakan pertanyaan lain kepada ghci
kind
, tetapi berhasil.undefined ::
Bagaimanapun menggunakan adalah semacam solusi, jadi saya pikir ini mungkin cukup.sumber
undefined ::
untuk memberikan contoh yang mudah. Masalah sebenarnya adalah ketika Anda mendapatkan pesan kesalahan yang memiliki jenis daftar seribu jenis yang berbeda. Dibutuhkan halaman untuk mencetaknya, dan sangat sulit untuk diurai.Ini diperbaiki dalam GHC 7.8 mendatang.
GHC 7.6 mencetak jenis jika tipe data menggunakan PolyKinds. Jadi Anda melihat,
(':) * String ('[] *)
bukan hanya(':) String '[]
.Di GHC 7.8, jenis tidak lagi ditampilkan secara default dan jenis data Anda cukup dicetak sebagai daftar, seperti yang Anda harapkan. Anda dapat menggunakan bendera baru
-fprint-explicit-kinds
untuk melihat jenis eksplisit seperti di GHC 7.6. Saya tidak tahu alasannya, mungkin jenis eksplisit dimaksudkan untuk membantu memahami PolyKinds.sumber
Saya memuatnya di ghci, lalu saya mengetik perintah berikut:
sumber
String ((':) * String ((':) * String ((':) * ...
.