异构列表的显示实例
Show instance for Heterogeneous List
我在为下面定义的异构列表定义 Show 实例时遇到问题:
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeInType #-}
{-# LANGUAGE FlexibleInstances #-}
import Data.Kind
data HList xs where
HNil :: HList TNil
(::^) :: a -> HList as -> HList (a :^ as)
data TypeList = TNil | (:^) Type TypeList
instance Show (HList TNil) where
show HNil = "[]"
我想给HList xs 一个show 实例,如果Typelist xs 中的所有类型都有一个Show Instance。我想应该可以写出类似
的东西
instance (Show a, _) => Show (HList a :^ as) where
show (x ::^ xs) = show x ++ show xs
但我不确定该填什么_.
PS:如果你在 ghci 中尝试这个,不要忘记添加语言扩展
:set -XTypeInType -XTypeOperators
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeInType #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
import Data.Kind
infixr 5 ::^
data HList xs where
HNil :: HList TNil
(::^) :: a -> HList as -> HList (a :^ as)
data TypeList = TNil | (:^) Type TypeList
instance Show (HList TNil) where
show HNil = "HNil"
instance (Show a, Show (HList as)) => Show (HList (a:^as)) where
showsPrec p (x::^xs) = showParen (p>5)
$ showsPrec 6 x . ("::^"++) . showsPrec 5 xs
main :: IO ()
main = print ((2 :: Int) ::^ "bla" ::^ HNil)
2::^"bla"::^HNil
使用类型族,您可以非常直接地表达约束 "All types have a show instance":
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeInType #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE UndecidableInstances #-}
import Data.Kind
infixr 5 ::^
data HList xs where
HNil :: HList TNil
(::^) :: a -> HList as -> HList (a :^ as)
data TypeList = TNil | (:^) Type TypeList
type family All (c :: Type -> Constraint) (xs :: TypeList) :: Constraint where
All c TNil = ()
All c (x :^ xs) = (c x, All c xs)
instance All Show xs => Show (HList xs) where
show HNil = "[]"
show (x ::^ xs) = '[' : show x ++ go xs
where
go :: All Show ys => HList ys -> String
go HNil = "]"
go (y ::^ ys) = ',' : show y ++ go ys
我在为下面定义的异构列表定义 Show 实例时遇到问题:
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeInType #-}
{-# LANGUAGE FlexibleInstances #-}
import Data.Kind
data HList xs where
HNil :: HList TNil
(::^) :: a -> HList as -> HList (a :^ as)
data TypeList = TNil | (:^) Type TypeList
instance Show (HList TNil) where
show HNil = "[]"
我想给HList xs 一个show 实例,如果Typelist xs 中的所有类型都有一个Show Instance。我想应该可以写出类似
的东西instance (Show a, _) => Show (HList a :^ as) where
show (x ::^ xs) = show x ++ show xs
但我不确定该填什么_.
PS:如果你在 ghci 中尝试这个,不要忘记添加语言扩展
:set -XTypeInType -XTypeOperators
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeInType #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
import Data.Kind
infixr 5 ::^
data HList xs where
HNil :: HList TNil
(::^) :: a -> HList as -> HList (a :^ as)
data TypeList = TNil | (:^) Type TypeList
instance Show (HList TNil) where
show HNil = "HNil"
instance (Show a, Show (HList as)) => Show (HList (a:^as)) where
showsPrec p (x::^xs) = showParen (p>5)
$ showsPrec 6 x . ("::^"++) . showsPrec 5 xs
main :: IO ()
main = print ((2 :: Int) ::^ "bla" ::^ HNil)
2::^"bla"::^HNil
使用类型族,您可以非常直接地表达约束 "All types have a show instance":
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeInType #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE UndecidableInstances #-}
import Data.Kind
infixr 5 ::^
data HList xs where
HNil :: HList TNil
(::^) :: a -> HList as -> HList (a :^ as)
data TypeList = TNil | (:^) Type TypeList
type family All (c :: Type -> Constraint) (xs :: TypeList) :: Constraint where
All c TNil = ()
All c (x :^ xs) = (c x, All c xs)
instance All Show xs => Show (HList xs) where
show HNil = "[]"
show (x ::^ xs) = '[' : show x ++ go xs
where
go :: All Show ys => HList ys -> String
go HNil = "]"
go (y ::^ ys) = ',' : show y ++ go ys