繁体   English   中英

使用高阶函数和联合生成集合

[英]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]

也就是说,最大输出值来自两个最小输入值。

因此,我们在某种程度上被迫分两步解决问题:

  1. 以任何顺序产生fxy输出值
  2. 对步骤 1 中生成的列表进行排序。

让我们调用第 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 ,它可以将一个列表分成大致相等的两个部分,我们可以通过以下方式获得我们自己的排序函数:

  1. 拆分输入列表
  2. 递归排序它的两半
  3. 使用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)

最后我们可以通过结合mySortcartesianFunc来提出我们的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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM