Haskell:如何将多个实例放在同一个模块中? [英] Haskell: How to put multiple instances in the same module?
问题描述
假设我有以下代码:
import Data.List.Ordered
data Person = Person String String
deriving(Show,Eq)
$ b $ main :: IO()
main = print。显示 。 (PersonJohannesKepler)]
在同一个模块中,我希望能够按名字和姓氏对列表进行排序。很显然,我不能这样做:
$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $比较(Person _ xLast)(Person _ yLast )=比较x最后y最后
实例Ord Person其中
比较(Person xFirst _)(Person yFirst _)= compare xFirst yFirst
那么,我的选择是什么?
这个页面提到你可以通过将类型包装成新类型并将所有需要的实例提升为新类型来实现这一点。有人可以举一个例子吗?
有没有更好的方法?
newtype方法是:
newtype ByFirstname = ByFirstname {unByFirstname :: Person}
实例Ord ByFirstname其中
- 模式匹配(ByFirstname(Person xFirst _))等
比较[...] = [...]
newtype ByLastname = ByLastname {unByLastname :: Person}
实例Ord ByLastname其中
- 如上
然后排序函数会是这样的:
sortFirstname = map unByFirstname。排序。 map ByFirstname
以及类似的 ByLastname
。
更好的方法是使用 sortBy
,比较
和 on
,其中包含检索名字和姓氏的函数。即
sortFirstname = sortBy(比较`on`名字)
$ b $(在这个注释中,对于 Person
,也可以使用记录类型,即 data Person = Person {firstName :: String,lastName :: String}
,其中一个甚至可以免费获得访问器函数。) Let's say that I have the following code:
import Data.List.Ordered
data Person = Person String String
deriving (Show, Eq)
main :: IO ()
main = print . show . sort $ [(Person "Isaac" "Newton"), (Person "Johannes" "Kepler")]
And in the same module, I want to be able to sort the list by both first name and by last name. Obviously I can't do this:
instance Ord Person where
compare (Person _ xLast) (Person _ yLast) = compare xLast yLast
instance Ord Person where
compare (Person xFirst _) (Person yFirst _) = compare xFirst yFirst
So, what are my options?
This page mentions "You can achieve this by wrapping the type in a newtype and lift all required instances to that new type." Can someone give an example of that?
Is there a better way?
The newtype method would be:
newtype ByFirstname = ByFirstname { unByFirstname :: Person }
instance Ord ByFirstname where
-- pattern matching on (ByFirstname (Person xFirst _)) etc
compare [...] = [...]
newtype ByLastname = ByLastname { unByLastname :: Person }
instance Ord ByLastname where
-- as above
Then the sorting function would be something like:
sortFirstname = map unByFirstname . sort . map ByFirstname
and similarly for ByLastname
.
A better way is to use sortBy
, compare
and on
, with functions for retrieving the first and last names. i.e.
sortFirstname = sortBy (compare `on` firstName)
(On that note, it might be worth using a record type for Person
, i.e. data Person = Person { firstName :: String, lastName :: String }
, and one even gets the accessor functions for free.)
这篇关于Haskell:如何将多个实例放在同一个模块中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!