如何在Haskell中打印自定义数据类型的名称和值

时间:2014-03-25 03:28:57

标签: function haskell types show

假设我将数据类型定义如下:

data OP = Plus | Minus | Num Int     deriving (Show, Eq)

然后我会列出strings列表,并获取各自OP值的列表,如下所示:

getOp :: [String] -> [OP]
getOp [] = []
getOp (x:rest)
        | x == "+" = Plus:(getOp rest)
        | isInfixOf "Num" x == True = Num (read (drop 4 x) :: Int):(getOp rest)
        | otherwise = "-" = Minus:(getOp rest)

然后我要显示[OP]列表,用新行分隔。我已经轻松完成了字符串列表,但不确定如何处理数据类型列表。

我有以下结构作为起点:

showOp :: [OP] -> String
showOp [] = []
showOp (o:os) = (putStr o):'\n':(showOp os)

我知道最后一行是错的。我试图在第一部分中返回[Char],然后是Char,然后是递归调用。我尝试了最后一行的其他变种(见下文)但没有运气。

showOp o = show o  (works but not what I need. It shows the whole list, not each element on a new line

showOp o = putStrLn (show o)   (epic fail)

showOp o 
    | o == "+" = "Plus\n":(showOp os)
    | more of  the same. Trying to return a [Char] instead of a Char, plus other issues.

另外,我不确定Num Int类型的输出需要如何不同,因为我需要显示类型名称和值。

这样的示例i / o类似于:

in:

getOp ["7","+","4","-","10"]

out:

Num 7
Plus
Num 4
Minus
Num 10

2 个答案:

答案 0 :(得分:4)

您需要查看正在使用的函数和对象的类型Hoogle是获取功能签名的绝佳资源。

首先,putStr的签名是

putStr :: String -> IO ()

但您的代码有putStr o,其中o不是字符串,结果不应该是IO ()。您真的希望showOp 打印 Op,还是只为它创建一个多行字符串?

如果是前者,则需要showOp的签名来反映:

showOp :: [Op] -> IO ()

然后你可以使用一些do - 符号来完成这个功能。

我会为您指定的类型签名编写解决方案。由于showOp应返回StringputStr返回IO (),因此我们无法在任何地方使用putStr。请注意,String只是[Char]的类型同义词,这就是我们可以将String视为列表的原因。

showOp :: [Op] -> String
showOp [] = [] -- the empty list is a String
showOp (o:os) = showo ++ ('\n' : showos)
   where showo = (show o) -- this is a String, i.e. [Char]
         showos = showOp os -- this is also a String

showoshowos都是StringshowshowOp都返回String。 我们可以使用cons操作:将单个字符添加到字符列表中。我们可以使用追加运算符++附加两个字符串列表。

现在你可能想要另一个功能

printOp :: [Op] -> IO ()
printOp xs = putStr $ showOp xs

答案 1 :(得分:3)

怎么样:

showOp = putStrLn . unlines . map show

请注意,您的数据构造函数OP已经是Show的实例。因此,您实际上可以map show进入包含OP类型成员的数组。在那之后,事情变得非常轻松。

快速的几个笔记......

你可能想要:

getOp :: [String] -> [OP]
getOp [] = []
getOp (x:rest)
        | x == "+"                  = Plus:(getOp rest)
        | x == "-"                  = Minus:(getOp rest)
        | isInfixOf "Num" x == True = Num (read (drop 4 x) :: Int):(getOp rest)
        | otherwise                 = (getOp rest)

而不是你拥有的。您的程序有语法错误...

接下来,您要提供的输入可能是

["Num 7","+","Num 4","-","Num 10"]

?我猜这是一个错字。