kind のパラメーターの単一の包括的なインスタンスを作成できます*
。
class MyClass d where
f :: d -> Int
instance MyClass (Maybe d) where
f _ = 3
test1 :: Maybe d -> Int
test1 x = f x
これは問題なくコンパイルされます。コンパイラは任意のMaybe d
.
型コンストラクターであるクラスパラメーターのすべてを網羅するインスタンスを作成することもできます。
class MyClass2 (a :: * -> *) where
g :: Tagged (a Int) Int
instance MyClass2 a where
g = Tagged 3
test2 :: Int
test2 = untag (g :: Tagged (Maybe Int) Int)
これも問題なくコンパイルされ、コンパイラが一致するインスタンスを見つけるため、test2 は (MyClass2 Maybe) 制約を必要としません。
(プロモートされた) 型リストの長さを計算するには、次のおもちゃのコードを検討してください。
{-# LANGUAGE TypeOperators,
DataKinds,
KindSignatures,
GADTs,
FlexibleInstances,
FlexibleContexts,
ScopedTypeVariables #-}
import Data.Tagged
import Data.Proxy
data HList :: [*] -> * where
HNil :: HList '[]
HCons :: a -> HList as -> HList (a ': as)
class ListLen a where
len :: Tagged a Int
instance ListLen (HList '[]) where
len = Tagged 0
instance (ListLen (HList as)) => ListLen (HList (a ': as)) where
len = Tagged (1+(untag (len :: Tagged (HList as) Int)))
test3 :: Int
test3 = untag (len :: Tagged (HList '[Int, Double, Integer]) Int)
test4 :: (Proxy (HList qs)) -> Int
test4 (_ :: Proxy (HList qs)) = untag (len :: Tagged (HList qs) Int) -- error occurs here
これにより、次のエラーが発生します。
No instance for (ListLen (HList qs))
arising from a use of `len'
Possible fix: add an instance declaration for (ListLen (HList qs))
...
の署名をコメントアウトするとtest4
、GHCi は型を次のように推論します。
test4 :: (ListLen (HList qs)) => (Proxy (HList qs)) -> Int
しかし、これは必要ありません。明らかに、考えられるすべての型リストに一致するインスタンスを作成しましListLen
た。「空リスト」の場合と「短所」の場合です。ListLen
パラメータの種類を変更して種類を変更しても (つまり、ラッパーとそのインスタンス[*]
を削除すると) 、問題は同じままです。HList
ListLen
をコメントアウトするtest4
と、コンパイルして正常に実行されます。型リストを構築する方法についてtest3
(本質的に) 明示的な構文 ( ) を指定したため、コンパイラは一致するインスタンスを見つけることができました。'[Int,Double,Integer]
型リストを作成するコードを書こうとしているので、明示的な型リスト構文を書き出す必要はありません。しかし、GHC がこれらの包括的なインスタンスに対応できる唯一の方法は、明示的な構文を使用することのようです。見落としているケースもあるのでは?使用していない構文
あらゆる種類のインスタンスがあることをGHCに認識させるにはどうすればよい[*]
ですか?
GHC 7.4.2 を使用しています。これは、昇格されていない型の分解に関する以前の投稿に関連している可能性があります。型の昇格に関する論文は、ここにあります。