如何在 Scala 中组合泛型方法?
How can I compose generic methods in Scala?
我正在学习 Scala 并且有以下玩具代码:
object M {
def isSorted[X](xs: Array[X], compare: (X, X) => Boolean): Boolean =
xs.dropRight(1).zip(xs.drop(1)).forall(Function.tupled(compare))
def curry[A,B,C](f: (A, B) => C) : A => (B => C) =
(a) => (b) => f(a, b)
}
我的目标是这样称呼它:
M.curry(M.isSorted)(Array(1,2,3))((a, b) => a < b)
但我收到错误消息:
scala> M.curry(M.isSorted)(Array(1,2,3))
<console>:8: error: type mismatch;
found : Int(1)
required: Nothing
M.curry(M.isSorted)(Array(1,2,3))
让我们回头看看柯里化函数的类型:
scala> M.curry(M.isSorted)
res2: Array[Nothing] => (((Nothing, Nothing) => Boolean) => Boolean) = <function1>
那可不行。它需要一个 Array[Nothing]
但不能有 Nothing
.
的实例
我知道在某些时候我需要引入一个约束,以便编译器可以证明表达式 a < b
是允许的;也就是说,a
和 b
是有序的。但我不知道我会把约束放在哪里。 curry
是完全通用的;约束不属于那里。 isSorted
对 compare
的实现一无所知,因此它也不属于那里。
我最接近让它工作的是 def isSorted[X >: Any]
scala> M.curry(M.isSorted)(Array(1,2,3))((a, b) => a < b)
<console>:8: error: value < is not a member of Any
M.curry(M.isSorted)(Array(1,2,3))((a, b) => a < b)
^
scala> M.curry(M.isSorted)(Array(1,2,3))((a: Int, b: Int) => a < b)
<console>:8: error: type mismatch;
found : (Int, Int) => Boolean
required: (Any, Any) => Boolean
M.curry(M.isSorted)(Array(1,2,3))((a: Int, b: Int) => a < b)
^
我怎样才能让它工作?
object M {
def isSorted[X](xs: Array[X], compare: (X, X) => Boolean): Boolean =
xs.dropRight(1).zip(xs.drop(1)).forall(Function.tupled(compare))
def curry[A,B,C](f: (A, B) => C) : A => (B => C) =
(a) => (b) => f(a, b)
}
嗯...我不认为这是定义这些函数的最佳方式,但在这种情况下,因为这些是通用函数,所以您需要在调用时为它们提供类型。
正如@dk14 在他的评论中指出的那样...M.sorted
无法获取类型信息,因为 Scala 缺乏对多态 lambda 的支持...这仅仅意味着匿名函数中没有泛型。
因此您需要针对此特定情况执行此操作。
M.curry( M.isSorted[Int] )( Array(1,2,3) ) ( (a , b) => a < b )
我正在学习 Scala 并且有以下玩具代码:
object M {
def isSorted[X](xs: Array[X], compare: (X, X) => Boolean): Boolean =
xs.dropRight(1).zip(xs.drop(1)).forall(Function.tupled(compare))
def curry[A,B,C](f: (A, B) => C) : A => (B => C) =
(a) => (b) => f(a, b)
}
我的目标是这样称呼它:
M.curry(M.isSorted)(Array(1,2,3))((a, b) => a < b)
但我收到错误消息:
scala> M.curry(M.isSorted)(Array(1,2,3))
<console>:8: error: type mismatch;
found : Int(1)
required: Nothing
M.curry(M.isSorted)(Array(1,2,3))
让我们回头看看柯里化函数的类型:
scala> M.curry(M.isSorted)
res2: Array[Nothing] => (((Nothing, Nothing) => Boolean) => Boolean) = <function1>
那可不行。它需要一个 Array[Nothing]
但不能有 Nothing
.
我知道在某些时候我需要引入一个约束,以便编译器可以证明表达式 a < b
是允许的;也就是说,a
和 b
是有序的。但我不知道我会把约束放在哪里。 curry
是完全通用的;约束不属于那里。 isSorted
对 compare
的实现一无所知,因此它也不属于那里。
我最接近让它工作的是 def isSorted[X >: Any]
scala> M.curry(M.isSorted)(Array(1,2,3))((a, b) => a < b)
<console>:8: error: value < is not a member of Any
M.curry(M.isSorted)(Array(1,2,3))((a, b) => a < b)
^
scala> M.curry(M.isSorted)(Array(1,2,3))((a: Int, b: Int) => a < b)
<console>:8: error: type mismatch;
found : (Int, Int) => Boolean
required: (Any, Any) => Boolean
M.curry(M.isSorted)(Array(1,2,3))((a: Int, b: Int) => a < b)
^
我怎样才能让它工作?
object M {
def isSorted[X](xs: Array[X], compare: (X, X) => Boolean): Boolean =
xs.dropRight(1).zip(xs.drop(1)).forall(Function.tupled(compare))
def curry[A,B,C](f: (A, B) => C) : A => (B => C) =
(a) => (b) => f(a, b)
}
嗯...我不认为这是定义这些函数的最佳方式,但在这种情况下,因为这些是通用函数,所以您需要在调用时为它们提供类型。
正如@dk14 在他的评论中指出的那样...M.sorted
无法获取类型信息,因为 Scala 缺乏对多态 lambda 的支持...这仅仅意味着匿名函数中没有泛型。
因此您需要针对此特定情况执行此操作。
M.curry( M.isSorted[Int] )( Array(1,2,3) ) ( (a , b) => a < b )