Операция 'cons' в Haskell, которая отображается как ее аналог в Scheme

В качестве упражнения я реализую на языке Haskell операцию 'cons', которая образует пару из двух значений любого типа. Реализовать нужный тип данных достаточно просто:

data Nil = Nil deriving (Eq)
data Pair a b = Cons a b deriving (Eq)

car (Cons x _) = x
cdr (Cons _ y) = y

caar = car . car
cdar = cdr . car
cadr = car . cdr
cddr = cdr . cdr

*Main> cddr (Cons 55 (Cons (1,2,3,4) "hello, world!"))
"hello, world!"
*Main> 

но, вдохновленный этой темой, я хочу, чтобы получающиеся пары выводились как списки Scheme - включая печально известный "неправильный список" (1 2 3 . 4). Моя реализация (см. ниже) работает для Char'ов:

*Main> Cons 'a' (Cons 'b' (Cons 'c' Nil))
('a' 'b' 'c')
*Main> Cons 'a' (Cons 'b' 'c')
('a' 'b' . 'c')
*Main> Cons (Cons 'a' 'b')(Cons 'c' (Cons 'd' Nil))
(('a' . 'b') 'c' 'd')

Она не очень хорошо работает для Int'ов (или любого другого типа данных). Поэтому мой вопрос: как я могу заставить это работать для других типов данных? То есть, я хочу, чтобы это работало так:

*Main> Cons 5 (Cons "hello" (Cons False Nil))
(5 "hello" False)

Моя текущая полная реализация выглядит так:

data Nil = Nil deriving (Eq)
data Pair a b = Cons a b deriving (Eq)

car (Cons x _) = x
cdr (Cons _ y) = y

caar = car . car
cdar = cdr . car
cadr = car . cdr
cddr = cdr . cdr

instance Show Nil where show _ = "()"

class ShowPair a where
  showRight::a->String

instance (Show a, ShowPair a, ShowPair b)=>Show (Pair a b) where
  show (Cons car cdr) = "(" ++ (show car) ++ (showRight cdr) ++ ")"

instance (Show a, ShowPair a, ShowPair b)=>ShowPair (Pair a b) where
  showRight (Cons car cdr) = " " ++ (show car) ++ (showRight cdr)

instance ShowPair Char where
  showRight x = " . " ++ show x

instance ShowPair Int where
  showRight x = " . " ++ show x

instance ShowPair Nil where
  showRight _ = ""

5
задан Community 23 May 2017 в 12:11
поделиться