gpt4 book ai didi

function - 将 scala 代码概括为函数

转载 作者:行者123 更新时间:2023-12-02 20:49:04 24 4
gpt4 key购买 nike

所以我最近不小心写了一个 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 类型系统屈服于我的意愿并将其概括为一个以 xscompare 为输入的函数(理想情况下) ,首先使用比较器柯里化(Currying)输入)。虽然这肯定是由于我对 Scala 普遍不熟悉,但我也有点责怪 Scala 复杂(尽管非常强大)的类型系统。您能否帮我指导一下如何将其转换为通用函数,并具有与 Haskell 等效项类似的类型签名? (阅读:一般。)如果比 myMaxBy(myCompare)(someList) 更复杂,还请演示用法。

最佳答案

您错过了case模式匹配中的关键字非常重要!

您所需要的只是集合参数类型能够使用 compare方法。 Scala 中有两个用于比较事物的系统:扩展 Ordered ,或使用Ordering 。两者之间存在隐式转换,因此您选择哪一个并不重要;第一个可能更容易理解。

首先,使用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使用 <% View 绑定(bind) ,这意味着“可以被视为”。这比使用上限 <: 更通用。 ,并且对于本身不是类的类很有用 Ordered ,但隐式转换为 Ordered类,例如IntRichInt .

或者,如果您希望能够灵活地更改排序标准,您可以这样编写:

  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]在范围内,您可以省略第二个参数。第二种方式还有一个优点,您可以定义 Ordering在任意类上,无论它们是否已经支持它。

您可以使用 myMaxBy(List(1,2,3,4,3,4)) 来调用两者。 。在第二个中,如果您想要反向排序:myMaxBy(List(1,2,3,4,3,4))(Ordering.Int.reverse) .

在此上下文中您可能会看到的另一件事是上下文边界。例如。 [A: Ordering] 。这意味着与 [A](implicit ord: Ordering[A]) 相同,这更简洁,只是您无法获取 Ordering 的句柄。所以必须使用 implicitly 来召唤它。因此,在这里最好像上面那样明确说明。

关于function - 将 scala 代码概括为函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8250109/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com