Scala中的类型类有什么用? [英] What are type classes in Scala useful for?

查看:73
本文介绍了Scala中的类型类有什么用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

据我从此博客文章所了解的Scala中的类"只是使用特征和隐式适配器实现的模式".

As I understand from this blog post "type classes" in Scala is just a "pattern" implemented with traits and implicit adapters.

如博客所述,如果我具有特征A和适配器B -> A,那么我可以调用一个函数,该函数需要类型为A的参数和一个类型为B的参数,而无需显式调用此适配器.

As the blog says if I have trait A and an adapter B -> A then I can invoke a function, which requires argument of type A, with an argument of type B without invoking this adapter explicitly.

我发现它不错,但不是特别有用.您能否给出一个用例/示例,以说明此功能的用途?

I found it nice but not particularly useful. Could you give a use case/example, which shows what this feature is useful for ?

推荐答案

一个用例,根据要求...

One use case, as requested...

假设您有一个东西列表,可以是整数,浮点数,矩阵,字符串,波形等.给定该列表,您想添加内容.

Imagine you have a list of things, could be integers, floating point numbers, matrices, strings, waveforms, etc. Given this list, you want to add the contents.

做到这一点的一种方法是具有某些Addable特性,该特性必须由可以添加在一起的每个单一类型继承,或者,如果处理来自第三方库的对象,则隐式转换为Addable您无法改装接口.

One way to do this would be to have some Addable trait that must be inherited by every single type that can be added together, or an implicit conversion to an Addable if dealing with objects from a third party library that you can't retrofit interfaces to.

当您还想开始添加可以对对象列表执行的其他此类操作时,这种方法很快就会变得不知所措.如果您需要其他选择,它也不能很好地工作(例如;添加两个波形是将它们串联还是叠加?)解决方案是临时多态性,您可以在其中可以选择行为并进行选择.改型为现有类型.

This approach becomes quickly overwhelming when you also want to begin adding other such operations that can be done to a list of objects. It also doesn't work well if you need alternatives (for example; does adding two waveforms concatenate them, or overlay them?) The solution is ad-hoc polymorphism, where you can pick and chose behaviour to be retrofitted to existing types.

那么对于最初的问题,您可以实现一个Addable类型的类:

For the original problem then, you could implement an Addable type class:

trait Addable[T] {
  def zero: T
  def append(a: T, b: T): T
}
//yup, it's our friend the monoid, with a different name!

然后,您可以创建此对象的隐式子类实例,这些实例与您希望使其可添加的每种类型相对应:

You can then create implicit subclassed instances of this, corresponding to each type that you wish to make addable:

implicit object IntIsAddable extends Addable[Int] {
  def zero = 0
  def append(a: Int, b: Int) = a + b
}

implicit object StringIsAddable extends Addable[String] {
  def zero = ""
  def append(a: String, b: String) = a + b
}

//etc...

然后对列表求和的方法变得很简单...

The method to sum a list then becomes trivial to write...

def sum[T](xs: List[T])(implicit addable: Addable[T]) =
  xs.FoldLeft(addable.zero)(addable.append)

//or the same thing, using context bounds:

def sum[T : Addable](xs: List[T]) = {
  val addable = implicitly[Addable[T]]
  xs.FoldLeft(addable.zero)(addable.append)
}

这种方法的优点在于,您可以提供某种类型类的替代定义,或者通过导入来控制想要在作用域中使用的隐式,或者通过显式提供否则为隐式的参数.因此,有可能提供不同的波形相加方式,或为整数相加指定模运算.将某些第三方库中的类型添加到类型类中也很容易.

The beauty of this approach is that you can supply an alternative definition of some typeclass, either controlling the implicit you want in scope via imports, or by explicitly providing the otherwise implicit argument. So it becomes possible to provide different ways of adding waveforms, or to specify modulo arithmetic for integer addition. It's also fairly painless to add a type from some 3rd-party library to your typeclass.

顺便说一句,这正是2.8 collections API所采用的方法.尽管sum方法是在TraversableLike而不是List上定义的,并且类型类是Numeric(它不仅包含zeroappend,还包含更多的操作)

Incidentally, this is exactly the approach taken by the 2.8 collections API. Though the sum method is defined on TraversableLike instead of on List, and the type class is Numeric (it also contains a few more operations than just zero and append)

这篇关于Scala中的类型类有什么用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆