I'm trying to make the types ghci displays for my libraries as intuitive as possible, but I'm running into a lot of difficulties when using more advanced type features.
Let's say I have this code in a file:
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
import GHC.TypeLits
data Container (xs::[*]) = Container
I load it up in ghci, then I type the following command:
ghci> :t undefined :: Container '[String,String,String,String,String]
Unfortunately, ghci gives me the rather ugly looking:
:: Container
((':)
*
String
((':)
* String ((':) * String ((':) * String ((':) * String ('[] *))))))
ghci has removed the sugar for type level strings. Is there any way to prevent ghci from doing this and giving me just the pretty version?
On a related note, lets say I create a type level Replicate
function
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
Now, when I ask ghci for a type using LotsOfStrings
:
ghci> :t undefined :: Container LotsOfStrings
ghci is nice and gives me the pretty result:
undefined :: Container LotsOfStrings
But if I ask for the Replicate
d version,
ghci> :t undefined :: Container (Replicate (Succ (Succ (Succ (Succ (Succ Zero))))) String)
ghci substitutes in for the type family when it didn't do that for the type synonym:
:: Container
((':)
*
[Char]
((':)
* [Char] ((':) * [Char] ((':) * [Char] ((':) * [Char] ('[] *))))))
Why is ghci doing the substitution for the type family, but not the type synonym? Is there a way to control when ghci will do the substitution?
The workaround that I know of is using :kind. For instance,
ghci> :kind (Container '[String,String,String,String,String])
Gives:
( Container '[String,String,String,String,String]) :: *
While
ghci> :kind! (Container '[String,String,String,String,String])
Will print something like this:
Container
((':)
* [Char] ((':) * [Char] ((':) * [Char] ((':) * [Char] ((':) * [Char] ('[] *))))))
Officially, of course, you're asking ghci a different question with kind
, but it works. Using undefined ::
is sort of a workaround anyhow, so I thought this might suffice.
This is fixed in upcoming GHC 7.8.
GHC 7.6 prints kinds if a datatype uses PolyKinds. So you see (':) * String ('[] *)
instead of just (':) String '[]
.
In GHC 7.8, kinds are no longer shown by default and your datatype is pretty printed as a list, as you would expect. You can use the new flag -fprint-explicit-kinds
to see explicit kinds as in GHC 7.6. I don't know the reasons for this, presumably explicit kinds were meant to be an aid for understanding PolyKinds.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With