2010-08-11 23 views
13

如果我有一个函数:为什么钻营和uncurrying Scala中没有隐含

f : A => B => C 

我可以定义这样的,这是可以用在一个函数(A, B) => C预期的隐式转换。这也是另一个方向。

为什么这些转换不是隐含(或隐式可用)?我假设不好的事情可能发生对于一些坏事的价值。这是什么价值?

回答

12

我不认为会发生什么坏事。转换是完全明确的。最糟糕的情况是,Scala将无法确定隐式转换是否适用。

implicit def curryImplicitly[A,B,C](f: (A, B) => C) = 
    (a: A) => (b: B) => f(a, b) 
implicit def uncurryImplicitly[A,B,C](f: A => B => C) = 
    (a: A, b: B) => f(a)(b) 

然后,这些也是有帮助的。

implicit def flipImplicitly[A,B,C](f: (A, B) => C) = 
    (b: B, a: A) => f(a, b) 
implicit def flipImplicitlyCurried[A,B,C](f: A => B => C) = 
    (b: B) => (a: A) => f(a)(b) 

但这些都不是传递的,所以你需要这些:

implicit def flipAndCurry[A,B,C](f: (A, B) => C) = 
    (b: B) => (a: A) => f(a, b) 
implicit def flipAndUncurry[A,B,C](f: A => B => C) = 
    (b: B, a: A) => f(a)(b) 

但现在的转换是不明确。所以这不是所有的玫瑰。

让我们知道它在实践中是如何实现的。您可能需要等同于Function3,Function4等。

+0

我在2.8版本中没有玩过这个游戏,但是我在2.7.X的黑暗时期尝试过这种方式,并且它倾向于导致编译器崩溃,在类型推理器iirc中。事情在这方面已经有了一些改进,所以现在可能现在都很好...... – 2010-08-11 22:14:59

+0

是的,如果你试图推断它是一个更高级的类型,那么编译器崩溃还是太容易了,但这是一个巨大的进步。 2.7。 – Apocalisp 2010-08-12 04:05:39

+0

我在2.8版中对这些简单案例进行了尝试,并且一切进展顺利。 – thSoft 2012-08-25 21:57:42

8

您不希望它们在默认情况下隐式可用(always-on),因为类型系统无法帮助您在重载参数时出现一堆相似的类型:

A => B => C 
D => C  // D is allowed to be a tuple (A,B)... 

(A,B) => C // If I have this, to whom should I convert? 

强键入的优势的一部分是警告你,当你做了一些愚蠢的事情。如果努力工作,让事情发挥作用就会降低收益。在这里,如果转换是自动完成的,您可能不会调用您打算调用的方法。

根据请求隐含提供它们是可以的,但如果您需要它并不是很难做到。这是我很少会用到的东西;我不会把它放在我在图书馆的前十名或者甚至是前百名的东西中(部分原因是我可能更喜欢自动转换为元组而不是自动加油/不加油)。

+4

请注意,您将无法使用参数'A => B => C'和'D => C'来重载函数,因为它们具有相同的擦除。所以这个问题在实践中不会出现。 – Apocalisp 2010-08-12 05:20:19

+0

啊,你是对的。如果您使用不同的方法名称,但将方法名称错误,那么将类型签名作为双重检查仍然会很有帮助。 – 2010-08-12 13:39:21

相关问题