异构列表是 ghc 7.6 的新依赖类型工具的示例之一:
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 专家可能会理解为什么这不起作用,我很乐意听到原因。
谢谢
汉斯·彼得
谢谢你,hammar,你的两个很好的工作示例,改进了我的第一个示例。
但我仍然不明白为什么我的第二个例子不起作用。您说“... 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)