我正在创建一个函数,检查两个无序多重集是否相等。
我有一个排序功能:
allsort :: (Ord a) => [a] -> [a]
allsort [] = []
allsort (x:xs) =
let smallerSorted = allsort [a | a <- xs, a <= x]
biggerSorted = allsort [a | a <- xs, a > x]
in smallerSorted ++ [x] ++ biggerSorted
和等式检查功能:
iEqual :: (Eq a) => [a] -> [a] -> Bool
iEqual [] [] = True
iEqual (x:xs) (y:ys) = x == y && iEqual xs ys
iEqual _ _ = False
我只是不知道如何将它们组合成一个函数或在iEqual中调用allsort ......
然后另一个想法是检查长度,如果x是y的子集。
编辑:我解决了它,只是比较了长度,然后如果它们是彼此的子集并且它有效。谢谢大家..答案 0 :(得分:5)
首先,将这些多重集声明为适当的不同类型:
newtype Multiset a = Multiset { getOrderedList :: [a] }
您希望能够从任何列表生成此类集,但保证始终排序。那么,
fromList :: Ord a => [a] -> Multiset a
fromList = Multiset . sort
(当然您也可以使用自定义排序功能,但the standard one会更有效率。)
现在,如果它们与有序列表相等,则两个多字节相等。这是一致的,因为我们确保Multiset
构造函数中的列表始终是!所以我们可以做到
instance (Eq a) => Eq (Multiset a) where
Multiset s == Multiset t = s == t
(同样,您也可以在这里使用iEqual s t
,但标准等式==
就可以了。)
请注意,如果您只是编写
,也可以自动生成此Eq
实例
newtype Multiset a = Multiset { getOrderedList :: [a] }
deriving (Eq)
(您还可以推导出其他有用的课程,我建议Show
,Generic
和Functor
。)
Prelude> newtype Multiset a = Multiset { getOrderedList :: [a] } deriving (Eq)
Prelude> :m +Data.List
Prelude Data.List> let fromList = Multiset . sort
Prelude Data.List> fromList [4,4,3] == fromList [3,4,4]
True
Prelude Data.List> fromList [4,4,3] == fromList [3,4,5]
False
答案 1 :(得分:2)
由于这看起来像是作业,我只会给出一个提示。
假设我们想以不区分大小写的方式比较字符串。我们有两个功能。第一个是sameString
,它检查两个字符串是否相等
sameString :: String -> String -> Bool
sameString = (==)
另一个将字符串转换为小写:
lowerString :: String -> String
lowerString = map toLower
我们现在可以将它们组合如下:
caseInsensitiveMatch :: String -> String -> Bool
caseInsensitiveMatch s1 s2 = sameString (lowerString s1) (lowerString s2)
(好的,这是一个很大的提示......; - ))