Haskell中的'cons'显示为与Scheme对应的

gcb*_*son 5 scheme haskell

作为练习,我在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> 
Run Code Online (Sandbox Code Playgroud)

但是受到这个主题的启发,我想让结果对打印出来像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')
Run Code Online (Sandbox Code Playgroud)

它对于Int(或任何其他数据类型)来说效果不佳.所以我的问题是:我如何才能将这项工作用于其他数据类型?即,我希望它像这样工作:

*Main> Cons 5 (Cons "hello" (Cons False Nil))
(5 "hello" False)
Run Code Online (Sandbox Code Playgroud)

我目前的全面实施如下:

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 _ = ""
Run Code Online (Sandbox Code Playgroud)

Tik*_*vis 6

这是一个选项.首先,通过将此行放在文件的顶部来启用这些扩展:

{-# LANGUAGE FlexibleInstances, OverlappingInstances, UndecidableInstances#-}
Run Code Online (Sandbox Code Playgroud)

接下来,删除您的ShowPair实例为CharInt.

现在ShowPair为以下内容添加实例Show:

instance Show a => ShowPair a where showRight = (" . " ++) . show
Run Code Online (Sandbox Code Playgroud)

现在,这确保了a作为实例的任何类型Show也是ShowPair通过.在其正常字符串形式之前添加a 来显示它的实例.但是,如果类型具有更具体的ShowPair实例(例如Nil),则Haskell将使用该实例.

这不是标准Haskell的一部分,因此您需要启用三种语言扩展.看看如何为另一个类型类中的所有类型编写实例?有关您需要扩展的原因的更多信息.