Haskell漂亮打印二维列表(失败说明)

Pretty-Printing 2D List in Haskell (Explanation of Failure)

Answers exist for how to pretty-print in Haskell, including how to do it with packages,但这更多的是关于为什么我的第一种方法失败的问题。

给定一个 w = [r,r1,r2] 形式的二维列表,其中 w、r 是各自的数据类型 w::Wr::R(示例中的简单变量,不是我的实际命名约定):

data X = Y | Z
         deriving (Eq, Show)

data R = [X]
         deriving (Eq, Show)

data W = [R]
         deriving (Eq, Show) 

为什么以下两种方法都行不通? (我完全知道这将包括方括号和逗号,这不是问题)

ppR :: R -> IO ()
ppR = putStrLn . show

ppW :: W -> IO W (?)
ppW (w:[]) = ppR w
ppW (w:ws) = ppR w >> ppW ws

ppW :: W -> IO W (?)
ppW (w:[]) = putStrLn . show w
ppW (w:ws) = putStrLn . show w >> ppW ws

我不太了解ppW的种类,还在学习中。除了我对 Haskell 对不纯函数的处理的明显天真(缺乏)理解之外,我还被 ppW 类型检查的第二种方法(没有提供类型)这一事实所困扰。

为什么这种方法不起作用?你能不能在 Haskell 中递归打印一个不确定长度的二维列表?

在您的情况下,类型应为 ppW :: W -> IO ()()(发音为 "unit")是一种只能有一个*值的类型 - 即 ()。所以 IO () 是一个 IO 操作,结果没有给出任何值(它等价于 C、C++ 或 Java 中的 void 函数)。

下面是一段应该编译的代码:

data X = Y | Z
  deriving (Eq, Show)

type R = [X]

type W = [R]

ppR :: R -> IO ()
ppR = putStrLn . show

ppW :: W -> IO ()
ppW (w:[]) = ppR w
ppW (w:ws) = ppR w >> ppW ws

如果您对类型有任何疑问,您可以随时使用 ghci 来确定任何函数的类型。或者您可以简单地查看您正在使用的函数类型:

putStrLn :: String -> IO()
(>>) :: IO a -> IO b -> IO b -- this is not exactly what ghci would tell you.

编辑: 在我包含的代码中,我使用 type 而不是 datatype 定义类型同义词(类似于 C/C++ typedef)。使用它们比使用 data 更容易 - data 要求您显式地写出构造函数的名称,因此您将拥有:

data R =  R [X]

ppR :: R -> IO ()
ppR (R r)= putStrLn (show r)

*其实也可以打底,那是另外一回事了