Показать экземпляр для гетерогенного списка - PullRequest
0 голосов
/ 13 мая 2018

У меня проблемы с определением экземпляров 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 (Show a, _) => Show (HList a :^ as) where
     show (x ::^ xs) = show x ++ show xs

но я не уверен, что заполнить дыру _.

PS: Если вы попробуете это в ghci, не забудьте добавить языковые расширения с помощью

:set -XTypeInType -XTypeOperators

Ответы [ 2 ]

0 голосов
/ 13 мая 2018

Используя семейства типов, вы можете выразить ограничение «Все типы имеют экземпляр show» довольно напрямую:

{-# 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
0 голосов
/ 13 мая 2018
{-# 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
...