2014-03-25 18 views
0

打印自定義數據類型的名稱和值可以說,我定義的數據類型,如下所示:如何在Haskell

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]列表,以換行分隔。我已經很容易地使用了Strings列表,但不知道如何處理數據類型列表。

,我有以下結構爲出發點:

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,這將是這樣的:

在:

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

出來:

Num 7 
Plus 
Num 4 
Minus 
Num 10 
+1

永遠不要說x ==真。只需說出x。 – augustss

回答

4

你需要看看類型的功能和你正在使用的對象。 Hoogle是獲取函數簽名的好資源。

對於初學者來說,中putStr簽名

putStr :: String -> IO() 

,但你的代碼有putStr o,其中o不是字符串,結果不應該是一個IO()。你真的想showOp打印Op,或者只是爲它做一個多行字符串?

如果是前者,你需要的showOp簽名,以反映:

showOp :: [Op] -> IO() 

然後你可以使用一些do -notation完成的功能。

我會爲您的給定類型簽名寫一個解決方案。由於showOp應返回StringputStr返回IO(),因此我們不會在任何地方使用putStr。請注意,String只是[Char]的一個類型同義詞,這就是爲什麼我們可以將String s作爲列表。

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 

兩個showoshowosString S:既showshowOp回報String秒。 我們可以使用cons操作:將單個字符添加到字符列表。我們可以使用附加運算符++附加兩個字符串列表。

現在,你可能想其他功能

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

這非常有幫助,謝謝。我唯一的問題是如何在不改變'[OP] - > String'簽名的情況下將printOp合併到showOp中,以便showOp的結果將每個元素放在輸出的新行上? – cHam

+3

注意:'showOp'只是'unlines。地圖顯示'。 – Zeta

+0

您不能*使用簽名'[Op] - > String'將'printOp'合併到'showOp'中。正如我上面所解釋的,有兩個單獨的步驟:將列表轉換爲一個String,並打印String。無論何時打印,您都需要在簽名中加入一個'IO()'。 *:從技術上講不是真的,但爲了您的目的,請考慮它。 – crockeea

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"] 

?我猜這是一個錯字。

+1

請注意,如果你想保留你的類型簽名,只需擺脫'putStrLn'函數... – ssm