Ghci desugar tip listeleri ve tip aileleri neden? Bu seçici olarak devre dışı bırakılabilir mi?


93

Kütüphanelerim için ghci görüntüleyen türleri olabildiğince sezgisel hale getirmeye çalışıyorum, ancak daha gelişmiş tür özelliklerini kullanırken çok fazla zorlukla karşılaşıyorum.

Diyelim ki bu kod bir dosyada var:

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

import GHC.TypeLits

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

Ghci'ye yükledim, sonra aşağıdaki komutu yazıyorum:

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

Ne yazık ki, ghci bana oldukça çirkin bir görünüm veriyor:

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

ghci, tür düzey dizeleri için şekeri kaldırdı. Ghci'nin bunu yapmasını ve bana sadece güzel versiyonu vermesini engellemenin bir yolu var mı?


İlgili bir notta, bir tür düzeyinde Replicateişlev oluşturduğumu varsayalım

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

Şimdi, ghci'den kullanarak bir tür istediğimde LotsOfStrings :

ghci> :t undefined :: Container LotsOfStrings

ghci güzel ve bana güzel bir sonuç veriyor:

undefined :: Container LotsOfStrings

Ama Replicated sürümünü sorarsam ,

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

ghci, tür eşanlamlısı için bunu yapmadığında, tür ailesinin yerine geçer:

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

Ghci neden tür ailesinin yerini alıyor, ancak türle eşanlamlı değil? Ghci'nin ikameyi ne zaman yapacağını kontrol etmenin bir yolu var mı?


7
Tip eşanlamlıları tamamen insan tüketimi için tasarlandığından - türü bu şekilde yazmak / görmek istediğiniz için türü eşanlamlı yaptığınızı kabul ettiği için ikame yapmaz. Tip ailesiyle ikameyi yapar çünkü tip aileleri gerçekten bir türü görüntülemekle değil, hesaplamak / çıkarmakla ilgilidir.
AndrewC

Sorununuzun çözümü sorunuzda yatıyor - kısaltmak istiyorsanız bir tür eşanlamlısı yapın.
AndrewC

2
@AndrewC Yorumunuzla ilgili başka bir soru düşündüm: Neden Dizge türleri bazen bazen olarak [Char], bazen de olarak görüntüleniyor String?
Mike Izbicki

1
Ben düşünüyorum o kaynakta bulduğu tip eş anlamlılarını korumak için GHCi denemeden. Yani, bir işlevin türde olduğu bildirilirseString->String , sonucunun türü olarak görüntülenecektir String. Bununla birlikte, örneğin parçalardan bir tür oluşturması gerekiyorsa, örneğin "abc"(ile aynıdır 'a':'b':'c':[]) korunacak eşanlamlı yoktur. Bu saf bir spekülasyon.
n. zamirler 'm.

4
@nm: GHC'nin, tür değişkenlerinin adlarını korumak için benzer bir girişimde bulunduğuna dikkat edin, daha genel çıkarsanan türler daha az genel, açıkça adlandırılmış tür değişkenleriyle birleştiğinde. Açık tipin Stringtip değişkenleriyle birleştirilmiş olması durumunda f aveya benzer nedenlerden dolayı daha sonra [a]görüntüleneceğinden şüpheleniyorum [Char].
CA McCann

Yanıtlar:


2

Bildiğim geçici çözüm kullanmak: tür. Örneğin,

ghci>: tür (Kapsayıcı '[Dize, Dize, Dize, Dize, Dize])

Verir:

(Kapsayıcı '[Dize, Dize, Dize, Dize, Dize]) :: *

Süre

ghci>: tür! (Kapsayıcı '[Dize, Dize, Dize, Dize, Dize])

Bunun gibi bir şey yazdıracak:

Konteyner

((':]

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

Resmi olarak, tabii ki, ghci'ye farklı bir soru soruyorsunuz kind, ama işe yarıyor. Kullanmak undefined ::zaten bir çeşit geçici çözüm, bu yüzden bunun yeterli olabileceğini düşündüm.


Ben sadece undefined ::kolay bir örnek vermek için kullanıyordum . Gerçek sorun, binlerce farklı türde bir liste içeren bir hata mesajı aldığınızda ortaya çıkar. Yazdırmak için sayfa gerekir ve ayrıştırılması çok zordur.
Mike Izbicki

Evet, yeterince adil. Coulda bunu anladı. Sana daha iyi bir cevap borçluyum
user2141650

2

Bu, gelecek GHC 7.8'de düzeltilmiştir.

Bir veri türü PolyKinds kullanıyorsa GHC 7.6 türleri yazdırır. Yani (':) * String ('[] *)sadece yerine görüyorsunuz (':) String '[].

GHC 7.8'de, türler artık varsayılan olarak gösterilmez ve veri türünüz, beklediğiniz gibi bir liste olarak oldukça yazdırılır. -fprint-explicit-kindsGHC 7.6'daki gibi açık türleri görmek için yeni bayrağı kullanabilirsiniz . Bunun nedenlerini bilmiyorum, muhtemelen açık türlerin PolyKinds'i anlamak için bir yardımcı olması gerekiyordu.


0
import GHC.TypeLits

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

Ghci'ye yükledim, sonra aşağıdaki komutu yazıyorum:

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

Yani...? Sanırım yine de sonucu geri alıyorsunuz, yani String ((':) * String ((':) * String ((':) * ....
leftaroundabout
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.