私のライブラリでghciが表示するタイプをできるだけ直感的にしようとしていますが、より高度なタイプ機能を使用すると、多くの困難に直面しています。
このコードがファイルにあるとしましょう:
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
import GHC.TypeLits
data Container (xs::[*]) = Container
それをghciにロードしてから、次のコマンドを入力します。
ghci> :t undefined :: Container '[String,String,String,String,String]
残念ながら、ghciは私にかなり醜い見た目を与えます:
:: Container
((':)
*
String
((':)
* String ((':) * String ((':) * String ((':) * String ('[] *))))))
ghciは型レベル文字列の砂糖を削除しました。ghciがこれをして、私にきれいなバージョンを与えるのを防ぐ方法はありますか?
関連するメモとして、タイプレベルのReplicate
関数を作成するとします。
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
今、私が使用するタイプをghciに尋ねるとLotsOfStrings
:
ghci> :t undefined :: Container LotsOfStrings
ghciは素晴らしく、かなりの結果が得られます。
undefined :: Container LotsOfStrings
しかし、Replicate
dバージョンを要求すると、
ghci> :t undefined :: Container (Replicate (Succ (Succ (Succ (Succ (Succ Zero))))) String)
型の同義語の代わりにghciが型ファミリーを置き換えます:
:: Container
((':)
*
[Char]
((':)
* [Char] ((':) * [Char] ((':) * [Char] ((':) * [Char] ('[] *))))))
ghciが型の同義語ではなく型ファミリーの代わりをしているのはなぜですか?ghciが置換を行うタイミングを制御する方法はありますか?
[Char]
、時々表示されるのString
ですか?
String->String
その結果の型はとして表示されString
ます。ただし、たとえば"abc"
(と同じ'a':'b':'c':[]
)のように、ピースから型を構築する必要がある場合、保持する同義語はありません。これは純粋な推測です。
String
が型変数f a
or [a]
で統一されて[Char]
同様の理由で後で表示されるとます。