我如何按名字对动物进行分类?名称由String
值表示。
data Animal = Cat String | Dog String | Fox String deriving (Show)
testAnimals = [(Dog "c"),(Fox "a"),(Cat "b")]
sortAnimalsByName :: [Animal] -> [Animal]
sortAnimalsByName animals = undefined
查询:
sortAnimalsByName testAnimals
应该返回:
[(Fox "a"),(Cat "b"),(Dog "c")]
我认为应该使用sort :: Ord a => [a] -> [a]
中的Data.List
函数,但是如何使用?
答案 0 :(得分:8)
首先,您最好定义一个public class DeviceEnumValidator<T> : PropertyValidator {
public DeviceEnumValidator()
: base("Invalid Enum value!") { }
protected override bool IsValid(PropertyValidatorContext context) {
DeviceTypes enumVal= (DeviceTypes) Enum.Parse(typeof(DeviceTypes), context.PropertyValue);
if (!Enum.IsDefined(typeof(DeviceTypes), enumVal)
return false;
return true;
}
}
函数:
public CheckUpdateVMValidator()
{
RuleFor(x => x.Device).SetValidator(new DeviceEnumValidator<DeviceTypes>());
}
只需使用sortBy
,其中比较器只是compare
但on
animalName
:
animalName :: Animal -> String
animalName (Cat n) = n
animalName (Dog n) = n
animalName (Fox n) = n
或者你可以 - 像@JonPurdy建议的那样,使用与animalName
基本相同的import Data.Function(on)
import Data.List(sortBy)
sortAnimalsByName :: [Animal] -> [Animal]
sortAnimalsByName = sortBy (compare `on` animalName)
:
comparing
甚至更短:
on compare
如果您使用record-syntax:
,则可以进一步省略import Data.Ord(comparing)
sortAnimalsByName :: [Animal] -> [Animal]
sortAnimalsByName = sortBy (comparing animalName)
的定义
import Data.List(sortOn)
sortAnimalsByName :: [Animal] -> [Animal]
sortAnimalsByName = sortOn animalName
答案 1 :(得分:3)
已编辑感谢@WillemVanOnsem的评论。
首先,这应该是一个正确的和类型,这样你就可以避免重复使用String。意思是,你应该成功
type Animal a = Dog a | Cat a | Fox a
这样你会有一个更普通的动物类型(这是一件好事)。更通用类型的一个优点是它允许您创建更精确的动态类型类实例。
但是在您的情况下,最简单的方法是派生Show
,Eq
,然后像这样写一个Ord实例:
data Animal = Cat String | Dog String | Fox String deriving (Show, Eq)
instance Ord Animal where
(Cat x) `compare` (Cat y) = x `compare` y
(Cat x) `compare` (Dog y) = x `compare` y
(Cat x) `compare` (Fox y) = x `compare` y
(Dog x) `compare` (Cat y) = x `compare` y
(Dog x) `compare` (Dog y) = x `compare` y
(Dog x) `compare` (Fox y) = x `compare` y
(Fox x) `compare` (Cat y) = x `compare` y
(Fox x) `compare` (Dog y) = x `compare` y
(Fox x) `compare` (Fox y) = x `compare` y
或
data Animal a = Cat a | Dog a | Fox a deriving (Show, Eq)
instance Ord a => Ord (Animal a) where
(Cat x) `compare` (Cat y) = x `compare` y
(Cat x) `compare` (Dog y) = x `compare` y
(Cat x) `compare` (Fox y) = x `compare` y
(Dog x) `compare` (Cat y) = x `compare` y
(Dog x) `compare` (Dog y) = x `compare` y
(Dog x) `compare` (Fox y) = x `compare` y
(Fox x) `compare` (Cat y) = x `compare` y
(Fox x) `compare` (Dog y) = x `compare` y
(Fox x) `compare` (Fox y) = x `compare` y
您可以使用sort
,因为现在Animal
有Ord
个实例
-- sort :: Ord a => [a] -> [a]
sort testAnimals
要点是:使用类型类。这只是简单类型的最简单方法。
答案 2 :(得分:0)
加入@Willem Van Onsem(记录语法)和@urbanslug(实现Ord
类实例)给出的答案,我们得到了最简单的答案:
data Animal a = Cat {name :: a}
| Dog {name :: a}
| Fox {name :: a} deriving (Show, Eq)
instance Ord a => Ord (Animal a) where
a1 `compare` a2 = name a1 `compare` name a2
因此可以简单地说
λ> sort [(Dog "c"),(Fox "a"),(Cat "b")]
[Fox {name = "a"},Cat {name = "b"},Dog {name = "c"}]
使用Data.Ord.comparing
函数更准确地写一个coud:
instance Ord a => Ord (Animal a) where compare = comparing name