異種リストは、ghc 7.6 の新しい従属型機能のために与えられた例の 1 つです。
data HList :: [*] -> * where
HNil :: HList '[]
HCons:: a -> HList t -> HList (a ': t)
リスト "li" の例は問題なくコンパイルされます。
li = HCons "Int: " (HCons 234 (HCons "Integer: " (HCons 129877645 HNil)))
当然、HList を Show クラスに含めたいと考えていますが、相互に再帰的な制約 (スーパークラス) を使用する次の作業クラスのインスタンス化しか考えられません。
instance Show (HList '[]) where
show HNil = "[]"
instance (Show a, Show' (HList t)) => Show (HList (a ': t)) where
show l = "[" ++ show' l ++ "]"
class Show' a where
show' :: a -> String
instance Show' (HList '[]) where
show' HNil = ""
instance (Show a, Show' (HList t)) => Show' (HList (a ': t)) where
show' (HCons h l) = case l of
HNil -> show h
HCons _ _ -> show h ++ ", " ++ (show' l)
コードは正常にコンパイルされ、li が適切に表示されます。必要なコンパイル フラグは次のとおりです。
{-# LANGUAGE DataKinds, TypeOperators, KindSignatures,
FlexibleContexts, GADTs, FlexibleInstances #-}
次のはるかに直接的な定義の多くのバリエーションを試しましたが、ghc エラー メッセージを理解できなければコンパイルできません。
instance Show (HList '[]) where
show HNil = "[]"
instance (Show a, Show (HList t)) => Show (HList (a ': t)) where
show l = "[" ++ (show' l) ++ "]" where
show' (HCons h s) = case s of
HNil -> show h
HCons _ _ -> show h ++ ", " ++ (show' s)
一部の Haskell / ghc スペシャリストは、これが機能しない理由を理解している可能性があり、その理由を喜んで聞きます。
ありがとうございました
ハンス・ペーター
私の最初の例を改善した、2 つの素晴らしい実例をありがとう、hammar。
しかし、2 番目の例が機能しない理由はまだわかりません。あなたは、「... show は現在の要素タイプのみを表示する方法を知っており、残りのタイプを表示する方法を知らない」と言います。しかし、そのコメントは次の (作業中の) コードにも当てはまりません:
instance Show (HList '[]) where show HNil = ""
instance (Show a, Show (HList t)) => Show (HList (a ': t)) where
show (HCons h t) = case t of
HNil -> show h
HCons _ _ -> show h ++ ", " ++ (show t)