Scala 解析'Show'类型类实例的隐式

Scala 解析'Show'类型类实例的隐式,scala,implicit,Scala,Implicit,我试图让Gender实现Showtypeclass scala> trait Gender extends Show[Gender] defined trait Gender scala> case object Male extends Gender defined object Male scala> case object Female extends Gender defined object Female 接下来,我定义了一个函数,该函数在隐式show[a]上调

我试图让
Gender
实现
Show
typeclass

scala> trait Gender extends Show[Gender]
defined trait Gender

scala> case object Male extends Gender
defined object Male

scala> case object Female extends Gender
defined object Female
接下来,我定义了一个函数,该函数在隐式
show[a]
上调用
show

scala> def f[A : Show](x: A): String = implicitly[Show[A]].shows(x)
f: [A](x: A)(implicit evidence$1: scalaz.Show[A])String
最后,我为
Show[Gender]
创建了一个隐式类:

scala> implicit class GenderShows(g: Gender) extends Show[Gender] {
     |    g match {
     |      case Male   => "Male"
     |      case Female => "Female"
     |    }
     | }
defined class GenderShows
我试过了,但没有发现这样的含蓄:

scala> val male: Gender = Male
male: Gender = Male

scala> f(male)
<console>:20: error: could not find implicit value for 
     evidence parameter of type scalaz.Show[Gender]
              f(male)
               ^
scala>val男性:性别=男性
男:性别=男
scala>f(男性)
:20:错误:找不到的隐式值
scalaz.Show类型的证据参数[性别]
f(男)
^

类型类的工作原理并非如此。不是在类定义中扩展类型类,而是单独为类型提供一个实例作为隐式值:

import scalaz._, Scalaz._

trait Gender
case object Male extends Gender
case object Female extends Gender

implicit val GenderShows: Show[Gender] = Show.shows {
  case Male   => "Male"
  case Female => "Female"
}

def f[A: Show](x: A): String = implicitly[Show[A]].shows(x)
然后:

scala> val male: Gender = Male
male: Gender = Male

scala> f(male)
res0: String = Male

这是类型类相对于子类型化的一大优势。它们将数据类型的定义与您希望在这些类型上支持的操作的定义分离开来(例如,没有人希望每次需要支持新的序列化库时都必须更改继承层次结构)。

谢谢,Travis。而
中的
Show
显示。Show
是特征,而不是
特征,我明白了。这种方法,即使用
Show[Gender]
Show#shows
定义,是定义
Show[A]
的惯用方法吗?
Show.Show
是一种方便的方法,允许您从函数
A=>String
A
创建一个
Show
实例。您还可以使用
newshow[A]{…}
——它只是更详细一些,更不惯用。如果您在性别伴侣对象中定义隐式val,那么编译器将始终找到它,即使它不是显式的imported@Daenyth是的,值得一提。