7

異種リストは、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) 
4

2 に答える 2

5

コメントで Nathan が言ったshow'ように、現在の要素の種類を表示する方法しかわかりません。残りの種類はわかりません。

最初の例のように、 の新しい型クラスを作成することでこれを回避できますが、インスタンスshow'が 1 つしかない場合でも回避できます。Show

-- Specializing show' to HLists avoids needing a Show' (HList ts) constraint
-- here, which would require UndecidableInstances.
instance (Show' ts) => Show (HList ts) where
  show xs = "[" ++ show' xs ++ "]"

class Show' ts where
  show' :: HList ts -> String

instance Show' '[] where
  show' HNil = ""

instance (Show a, Show' ts) => Show' (a ': ts) where
  show' (HCons a s) = case s of
    HNil     -> show a
    HCons {} -> show a ++ ", " ++ show' s

Show必要なすべての制約を取得する別のよりハックな方法は、必要なすべての制約のリストを直接作成するためshow'に使用することです。ConstraintKinds

-- In addition to the extensions in the original code:
{-# LANGUAGE TypeFamilies, ConstraintKinds, UndecidableInstances #-}
import GHC.Exts

-- ShowTypes [a, b, c, ...] = (Show a, Show b, Show c, ...)
type family ShowTypes (a :: [*]) :: Constraint
type instance ShowTypes '[] = ()
type instance ShowTypes (a ': t) = (Show a, ShowTypes t) 

instance ShowTypes ts => Show (HList ts) where
  show xs = "[" ++ show' xs ++ "]"
    where
      show' :: ShowTypes ts => HList ts -> String
      show' HNil = ""
      show' (HCons h s) = case s of
        HNil     -> show h
        HCons {} -> show h ++ ", " ++ show' s
于 2012-10-20T18:05:28.243 に答える