Haskell ghc-7.6相关类型的类实例
异构列表是ghc 7.6中新独立类型设施的示例之一:Haskell ghc-7.6相关类型的类实例,haskell,ghc,dependent-type,Haskell,Ghc,Dependent Type,异构列表是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类中,但我只能提出以下使
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类中,但我只能提出以下使用相互递归约束(超类)的工作类实例化:
代码编译得很好,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专家可能会理解为什么这不起作用,我很乐意听到原因
多谢各位
汉斯·彼得
谢谢你,哈马尔,为你的两个很好的工作例子,改进了我的第一个例子 但我仍然不明白为什么我的第二个例子不起作用。您说“…show”只知道如何显示当前的元素类型,而不知道如何显示其余的元素类型。”但该注释是否也适用于以下(工作)代码:
正如Nathan在评论中所说,
show'
只知道如何显示当前的元素类型,而不知道如何显示其余的元素类型
在第一个示例中,我们可以通过为show'
创建一个新的类型类来解决这个问题,尽管您只能使用一个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
多亏了哈马尔的第二个解决方案,我现在可以提供一种更通用的方法,它适用于普通类(但我想他无论如何都有这个想法):
再次感谢您的大力帮助。您是否尝试过
show'(HCons h HNil)=show h
,show'(HCons h s)=show h++>,“++show's
?show':对于所有的t。(Show a,Show(HList t))=>HList(a):t)->String
不提供任何约束,表明可以显示列表中的下一个元素。将其定义为HCons\uu->show h++“,“++show s
可以工作,但格式与您原来的示例不同。dbaupp:是的,我尝试过,但Nathan的评论适用于我原来的非工作解决方案以及您的提案。但我真的不明白。(请看下面的原因。)@wurmli我将您的编辑添加到了Hammers对您问题的回答中。如果您想要求澄清,请在注释中的适当位置。@wurmli AShow A,Show(HList t))
约束声明您可以显示列表的开头和结尾。它没有说明任何关于第N个元素(其中N>0)的内容,只是头和尾。带约束类型的类型族(Hammar的示例)或助手类型类(您的替代解决方案)是解决这一问题的两种方法。重新审视您的第二种解决方案,我实际上不仅觉得它“不错”,而且完全回答了我的问题,一点也不粗鲁。我一直在寻找一种方法来表达约束,您可以将其表示为一个类型族。我曾希望能够用实例定义来表达超类型的归纳。再次感谢你的帮助。
-- 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
-- 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
type family ConstrainedTypes (a :: [*]) (f :: * -> Constraint) :: Constraint
type instance ConstrainedTypes '[] b = ()
type instance ConstrainedTypes (a ': t) b = (b a, ConstrainedTypes t b)
instance ConstrainedTypes ts Show => Show (HList ts) where
show xs = "[" ++ show' xs ++ "]"
where
show' :: ConstrainedTypes ts Show => HList ts -> String
show' HNil = ""
show' (HCons h s) = case s of
HNil -> show h
HCons {} -> show h ++ ", " ++ show' s