我希望能够定义自定义数据类型,而不是使用类型别名来确保传递正确的值,下面是可能看起来如何的草图,
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
但是,我还希望保留基础类型的“list-ness”,而不必打开和重新包装[DictEntry]
,而无需定义实用程序函数,例如head :: Dictionary -> DictEntry
和tail :: Dictionary -> Dictionary
。那可能吗?是否有一些类型类我可以定义一个实例或一个语言扩展来启用它?
答案 0 :(得分:6)
永远不要使用head
并避免使用tail
,列表或其他。这些是不安全的,并且总是可以很容易地用模式匹配替换。
但是,是的,有一个类型类支持类似列表的操作,或者更确切地说是多个类。其中最简单的是Monoid
,它只实现连接和空初始化。 Foldable
,允许您解释容器,就像它们是列表一样。 Traversable
还允许您在浏览数据时再次组装它们。
后两者不能与Dictionary
完全兼容,因为它不是包含类型的参数。您可以通过切换到“monomorphic version”来规避这一点。
但是,我坦率地认为你不应该这样做 - 只需使用标准Map
类型来存储键值关联数据,而不是滚动自己的字典类型。