[英]Generating a set using higher order functions and unions
我正在研究过去的考试,我遇到了一个问题,我必须编写一个名为 setFunc 的函数来生成一个集合,在该集合中我对元组列表中的每个元素应用一个函数(这是笛卡尔积运算的结果)
首先,我实现了一个辅助函数来获取集合的并集:
然后我尝试实现主要功能:
setFunc x y = f x y
setFunc (x:xs) (y:ys) = (f x y) OrdUnion (setFunc f xt ys)
帮助修复 setFunc 将不胜感激。
我必须以某种方式使用
ordUnion
并且不允许使用sort
。
这种约束预计会出现在问题的正文中。
问题的核心部分是我们希望对输出列表进行排序(从您的示例中),但我们没有被告知参数函数可能的顺序保留属性。 所以我们必须接受fxy
输出值将以某种不可预测的随机顺序产生。
例如,我们期望这个等式成立:
setFunc (*) [-7,2] [-7,3] == [-21,-14,6,49]
也就是说,最大输出值来自两个最小输入值。
因此,我们在某种程度上被迫分两步解决问题:
fxy
输出值 让我们调用第 1 步函数cartesianFunc
。 以递归方式编写它很容易:
cartesianFunc :: Ord c => (a -> b -> c) -> [a] -> [b] -> [c]
cartesianFunc f [] ys = []
cartesianFunc f (x:xs) ys = (map (f x) ys) ++ (cartesianFunc f xs ys)
请注意,我们已经删除了类型 b 和 c 上无用的Ord
约束。
测试:
$ ghci
GHCi, version 8.8.4: https://www.haskell.org/ghc/ :? for help
...
λ>
λ> :load q13784671.hs
[1 of 1] Compiling Main ( q13784671.hs, interpreted )
Ok, one module loaded.
λ>
λ> cartesianFunc (*) [1,2,4] [1,3,9]
[1,3,9,2,6,18,4,12,36]
λ>
现在进行第 2 步:
我们可能不会使用库sort
功能。 但是我们必须使用函数ordUnion
,它将两个有序列表合并成一个更大的有序列表。
假设我们还有另一个函数,比如splitHalf
,它可以将一个列表分成大致相等的两个部分,我们可以通过以下方式获得我们自己的排序函数:
ordUnion
函数组合我们的两个排序的一半。要拆分列表,我们可以使用众所周知的龟兔算法,其中在每次迭代中,第一部分前进一步,第二部分前进两步。
这给出了这个代码:
ordUnion :: (Ord a) => [a] -> [a] -> [a]
ordUnion a [] = a
ordUnion [] b = b
ordUnion (x:xs) (y:ys) = case compare x y of
LT -> x : ordUnion xs (y:ys)
EQ -> x : ordUnion xs ys
GT -> y : ordUnion (x:xs) ys
splitHalfTH :: [a] -> ([a],[a])
splitHalfTH xs = th xs xs
where
th (y:ys) (_:_:zs) = let (as,bs) = th ys zs in (y:as, bs)
th ys _ = ([],ys)
mySort :: (Ord a) => [a] -> [a]
mySort [] = []
mySort [a] = [a]
mySort xs = let (as,bs) = splitHalfTH xs in ordUnion (mySort as) (mySort bs)
最后我们可以通过结合mySort
和cartesianFunc
来提出我们的setFunc
函数:
setFunc :: Ord c => (a -> b -> c) -> [a] -> [b] -> [c]
setFunc fn xs ys = mySort (cartesianFunc fn xs ys)
测试:
λ>
λ> cartesianFunc (*) [1,2,4] [1,3,9]
[1,3,9,2,6,18,4,12,36]
λ>
λ> mySort $ cartesianFunc (*) [1,2,4] [1,3,9]
[1,2,3,4,6,9,12,18,36]
λ>
λ> setFunc (*) [1,2,4] [1,3,9]
[1,2,3,4,6,9,12,18,36]
λ>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.