Estoy tratando de hacer que los tipos de visualización de ghci para mis bibliotecas sean lo más intuitivos posible, pero me encuentro con muchas dificultades al utilizar funciones de tipo más avanzadas.
Digamos que tengo este código en un archivo:
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
import GHC.TypeLits
data Container (xs::[*]) = Container
Lo cargo en ghci, luego escribo el siguiente comando:
ghci> :t undefined :: Container '[String,String,String,String,String]
Desafortunadamente, ghci me da un aspecto bastante feo:
:: Container
((':)
*
String
((':)
* String ((':) * String ((':) * String ((':) * String ('[] *))))))
ghci ha eliminado el azúcar para las cadenas de nivel de tipo. ¿Hay alguna forma de evitar que ghci haga esto y me dé la versión bonita?
En una nota relacionada, digamos que creo una Replicate
función de nivel de tipo
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
Ahora, cuando le pregunto a ghci por un tipo usando LotsOfStrings
:
ghci> :t undefined :: Container LotsOfStrings
ghci es agradable y me da un bonito resultado:
undefined :: Container LotsOfStrings
Pero si pido la Replicate
versión d,
ghci> :t undefined :: Container (Replicate (Succ (Succ (Succ (Succ (Succ Zero))))) String)
ghci sustituye a la familia de tipos cuando no hizo eso para el sinónimo de tipos:
:: Container
((':)
*
[Char]
((':)
* [Char] ((':) * [Char] ((':) * [Char] ((':) * [Char] ('[] *))))))
¿Por qué ghci sustituye la familia de tipos, pero no el sinónimo de tipos? ¿Hay alguna forma de controlar cuándo ghci hará la sustitución?