2017-01-27 5 views
0

型の別名を使用して適切な値が渡されることを保証するのではなく、カスタムデータ型を定義できるようにしたいと考えています。データ型のリスト操作の保持

module Example (fromList) where 

import Data.Ord (comparing, Down(..)) 
import Data.List (sort) 

data DictEntry = DictEntry (String, Integer) deriving (Show, Eq) 

instance Ord DictEntry where 
    (DictEntry (word1, freq1)) `compare` (DictEntry (word2, freq2)) 
    | freq1 == freq2 = word1 `compare` word2 
    | otherwise = comparing Down freq1 freq2 

data Dictionary = Dictionary [DictEntry] deriving (Show) 

fromList :: [(String, Integer)] -> Dictionary 
fromList l = Dictionary $ sort $ map DictEntry l 

しかし、私はまた、そのようなhead :: Dictionary -> DictEntrytail :: Dictionary -> Dictionaryなどのユーティリティ関数を定義することなく、アンラップと[DictEntry]を再ラップすることなく、基になる型の「リストらし」を維持したいと思います。それは可能ですか?これを可能にする言語拡張やインスタンスを定義できる型クラスがありますか?

+1

おそらく安全なキャストがラップ/アンラッピングを減らすのに役立つかもしれません。それ以外の場合は、カスタムパターン同義語を定義して、リストの場合と同様に 'Dictionary 'のパターンマッチングを可能にすることができます。 – chi

答えて

6

headを絶対に使用しないでください。tailをリストに使用しないでください。これらは安全ではなく、いつでも簡単にパターンマッチングに置き換えることができます。

しかし、はい、リストライクな操作、またはむしろ複数のクラスをサポートするtypeclassがあります。これらの中で最も簡単なものはMonoidです。これは連結と空の初期化だけを実装しています。 Foldableは、コンテナをリストのように分解することができます。 Traversableでは、データを上書きする際に、再度組み立てることができます。

Dictionaryの後者の2つは、含まれているタイプでパラメトリックではないため、正しく動作しません。 “monomorphic version”に切り替えることで回避できます。

しかし、私は率直に言って、これを行うべきではないと思います。あなた自身の辞書タイプを使う代わりに、標準のMapタイプを使用してキーと値の関連データを保存してください。

+0

「頭」と「尾」に関しては知っていますが、あなたが言及するのは良いことです。 私は「モノイド」を調べて、それが外に出ているように見えたら答えを受け入れます。 問題は、適切なマップではないということです。データは、主に 'snd'でソートされ、' fst'は副次的にソートされなければなりません。私は(おそらく) 'Data.Set'を使うことができました。しかし、私はまだリスト操作を使用したい。 'Monoid'(そして恐らく' Foldable'/'Traversable')は依然として適切でしょうか? –