将scala代码泛化为函数
所以我最近不小心为
Scala问题写了一个Haskell答案.相当熟悉Haskell,解决方案对我来说很容易:
myMaxBy :: (a -> a -> Ordering) -> [a] -> [a] myMaxBy _ [] = undefined myMaxBy f (x:xs) = foldr step [x] xs where step y acc@(z:_) = case f y z of GT -> [y] EQ -> y:acc LT -> acc 那么有人提醒我,这是一个Scala的问题.我开始将我的代码转移到Scala,经过很多痛苦,我决定: (List(xs.head) /: xs.tail) { (acc,y) => y compare acc.head match { 1 => List(y) 0 => y :: acc -1 => acc } } 但是,对于我来说,我不能让Scala类型系统屈服于我的意愿,并将其推广到一个xs和比较输入的函数(理想情况下,比较器首先输入参数).虽然这肯定是由于我对Scala的不熟悉,但我也轻率地责怪Scala的复杂(虽然非常强大)的系统.你可以做一些手持,走过我怎么可以把它变成一个泛化函数,类型签名类似于Haskell等价物? (阅读:一般如.)请同时演示使用,如果它比myMaxBy(myCompare)(someList)更复杂. 解决方法
你错过了你的模式匹配的案例关键字,这是非常重要的!
所有您需要的是收集参数类型才能使用比较方法.在Scala中有两种比较事物的系统:扩展顺序或使用排序.两者之间存在隐含的转换,所以您选择无关紧要;第一个可能更容易理解. 首先,使用Ordered: def myMaxBy[A <% Ordered[A]](xs: List[A]) = { (List(xs.head) /: xs.tail) { (acc,y) => y compare acc.head match { case 1 => List(y) case 0 => y :: acc case -1 => acc } } } 这里我们给我们的泛型类型A使用<%绑定的视图,这意味着“可以被看作”.这比使用上限<:更通用,并且对于本身不是有序的但对具有有序类的隐式转换是有用的. Int到RichInt. 或者,如果您希望灵活性能够更改订购条件,则可以这样写: def myMaxBy[A](xs: List[A])(implicit ord: Ordering[A]) = { (List(xs.head) /: xs.tail) { (acc,y) => ord.compare(y,acc.head) match { case 1 => List(y) case 0 => y :: acc case -1 => acc } } } 调用时,如果范围内有一个隐含的Ordering [A],则可以退出第二个参数.第二种方式也可以在任意类上定义一个排序,无论他们是否已经支持它. 您可以使用例如myMaxBy(List(1,2,3,4,4))来调用它们.在第二个,如果你想要的话,反向排序:myMaxBy(List(1,4))(Ordering.Int.reverse). 在这种情况下您可能会看到的另一件事情是上下文边界.例如. [A:订购].这意味着与[A](隐含的ord:Ordering [A])相同,这是更简洁的,除了你没有得到一个句柄的Ordering,所以必须使用隐含的召唤.所以在这里可能最好把它说明如上. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |