2011-12-16 70 views
3

我試圖使自定義類型爲Show的一個實例。在Haskell中的任意遞歸類型定義顯示

這裏是theType,它只是一個基本的Set類型。

data Set a = Insert a (Set a) | EmptySet 

我想是這樣

Insert 1 (Insert 2 (Insert 3 EmptySet)) 

,顯示一個類似

{1, 2, 3} 

我該怎麼辦呢?我嘗試使用字符串連接來完成它,但它似乎是做字符串插值被認爲是不好的形式(Haskell似乎並沒有本地支持這一點?)另外,我如何獲得列表中的花括號?到目前爲止,所有我能煮了是這樣的,基本上什麼也不做......

instance (Show a) => Show (Set a) where 
    show EmptySet = "" 
    show (Insert a as) = show a ++ show as 

而且,我試圖用Hoogle和Hayoo找到List實現,所以我可以看到這是如何實現的列表。我找不到它。有沒有人有這方面的指針?我試着搜索「show :: [a] - > String」,「Data.Lists」,「Lists」等....

+3

順便說一句,這可能是一個壞主意。 `show`的結果應該是有效的Haskell代碼,它的值等於傳給`show`的值。我建議定義一個`fromList`函數並在集合{1,2,3}上產生`show`,例如, `fromList [1,2,3]`;這是標準Data.Map和Data.Set庫採用的方法。或者,你可以定義你自己的函數來調用這個函數,而不是`show`來查看這個表示法中的集合。 – ehird 2011-12-17 00:29:30

回答

5

下面是與直接遞歸的解決方案:

instance Show a => Show (Set a) where 
    show = ('{' :) . go 
    where 
     go EmptySet   = "}" 
     go (Insert x EmptySet) = show x ++ "}" 
     go (Insert x xs)  = show x ++ ", " ++ go xs 

如果你不喜歡的低效利用(++),你當然可以用difference lists

instance Show a => Show (Set a) where 
    show = ('{' :) . ($ []) . go 
    where 
     go EmptySet   = ('}' :) 
     go (Insert x EmptySet) = shows x . ('}' :) 
     go (Insert x xs)  = shows x . (", " ++) . go xs 

這應該做到這一點;所以,讓我們測試:

> show (Insert 2 (Insert 3 (Insert 5 EmptySet))) 
"{2, 3, 5}" 
4

數據類型可能是遞歸的,但這並不是函數遞歸的原因。

import Data.List (intercalate) 

instance Show a => Show (Set a) where 
    show x = "{" ++ intercalate ", " (toList x) ++ "}" 

這假設你有一個功能toList :: Set a -> [a]。遞歸隱藏在那裏。

列表實現通過從Show typeclassshowList函數來完成(所以String S,又名[Char] S,可以以不同的顯示)。

+0

我是一個noob,但不打破,因爲列表必須包含所有相同類型的元素?如果我給這個函數提供一個數字列表,不是會出現類型錯誤嗎? – 2011-12-16 23:22:55

+1

您定義的集合也必須包含相同類型的元素。在「插入(設置)」中,全是「a」。所以應該沒有問題。 – redxaxder 2011-12-17 00:56:23

5

你的類型仍然與列表同態。無論哪個Show實例被定義;你仍然可以使用它:

toList (Insert a b) = a:toList b 
toList EmptySet = [] 

instance Show a => Show (Set a) where 
    show = show . toList