2011-12-16 20 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はこれをネイティブにサポートしていないようですか?)また、リストの中括弧はどうやって取得できますか?これまでのところ、私は調理することができたすべてはまた、私はこれが上に実装された方法を見ることができるようにリストの実装を見つけることHoogleとHayooを使用しようとした基本的に何もしないそれはこの、...

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

ましたリスト。私はそれを見つけることができませんでした。誰にもこれについての指針はありますか?私は "show :: [a] - > String"、 "Data.Lists"、 "Lists"などを検索しようとしました...

+3

ところで、これはおそらく悪い考えです。 'show'の結果は、' show'に渡されたものと等しい値を生成する有効なHaskellコードでなければなりません。 'fromList'関数を定義し、セット{1、2、3}上の' show'を生成することを提案します。 'fromList [1、2、3]';これは、標準のData.MapおよびData.Setライブラリで採用されているアプローチです。あるいは、この表記法でセットを表示するために 'show'の代わりに呼び出される独自の関数を定義することもできます。 – ehird

答えて

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}" 
+1

'(++)'の非効率的な使い方が気に入らなければ、 'show'ではなく' showsPrec'を実装するべきです。 –

+0

@SjoerdVisscher:もちろん、私は同意しますが、私は最初の実装でデルタを実証したかったのです。 –

4

データ型は再帰的かもしれませんが、これは再帰的な。

import Data.List (intercalate) 

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

ここでは、機能がtoList :: Set a -> [a]であることを前提としています。再帰はそこに隠されています。 (String S、別名[Char] sは、異なって表示させることができるように)

リスト実装はShow typeclassからshowList関数を介して行われます。

+0

私はまあまあですが、リストにはすべて同じタイプの要素が含まれていなければならないので、これは壊れませんか?この関数に数値のリストを入力した場合、型エラーが発生しませんか? –

+1

あなたが定義したセットには、同じタイプの要素も含まれている必要があります。 'Insert a(Set a)'では、すべて 'a'です。だから問題はないはずです。 – redxaxder

5

あなたのタイプはまだリストと同型です。どこでもShowインスタンスが定義されています。あなたはまだそれを使用することができます。

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

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