Scala类型类最佳实践
我正在阅读并通过使用类型类来解决这个问题,并且我从Shapeless指南中找到了这种定义类型类的方法:
所以这里是一个例子: object CsvEncoder { // "Summoner" method def apply[A](implicit enc: CsvEncoder[A]): CsvEncoder[A] = enc // "Constructor" method def instance[A](func: A => List[String]): CsvEncoder[A] = new CsvEncoder[A] { def encode(value: A): List[String] = func(value) } // Globally visible type class instances } 我不明白需要申请方法吗?在上面这个背景下它做了什么? 稍后,该指南描述了如何创建类型类实例: implicit val booleanEncoder: CsvEncoder[Boolean] = new CsvEncoder[Boolean] { def encode(b: Boolean): List[String] = if(b) List("yes") else List("no") } 实际上缩写为: implicit val booleanEncoder: CsvEncoder[Boolean] = instance(b => if(b) List("yes") else List("no")) 所以现在我的问题是,这是如何工作的?我没有得到的是需要申请方法? 编辑:我发现了一篇博客文章,描述了创建类型类的步骤,如下所示: >定义类型类合同特征Foo. 那么点数2,3和4的交易是什么? 解决方法
大多数这些实践来自Haskell(基本上是模仿Haskell类型类的意图是这么多模板的原因),其中一些只是为了方便起见.所以,
2)正如@Alexey Romanov所提到的,带有apply的伴随对象只是为了方便,所以你可以只编写CsvEncoder [IceCream](又名CsvEncoder.apply [IceCream]())而不是隐式[CsvEncoder [IceCream]],这将返回你是一个必需的类型类实例. 3)FooOps为DSL提供便利方法.例如,你可以有类似的东西: trait Semigroup[A] { ... def append(a: A,b: A) } import implicits._ //you should import actual instances for `Semigroup[Int]` etc. implicitly[Semigroup[Int]].append(2,2) 但有时调用append(2,2)方法很不方便,因此提供符号别名是一种很好的做法: trait Ops[A] { def typeClassInstance: Semigroup[A] def self: A def |+|(y: A): A = typeClassInstance.append(self,y) } trait ToSemigroupOps { implicit def toSemigroupOps[A](target: A)(implicit tc: Semigroup[A]): Ops[A] = new Ops[A] { val self = target val typeClassInstance = tc } } object SemiSyntax extends ToSemigroupOps 4)您可以按如下方式使用它: import SemiSyntax._ import implicits._ //you should also import actual instances for `Semigroup[Int]` etc. 2 |+| 2 如果你想知道为什么这么多样板文件,以及为什么scala的隐式类语法不能从头开始提供这个功能 – 答案是隐式类实际上提供了一种创建DSL的方法 – 它只是不那么强大 – 它(主观上)提供操作更难别名,处理更复杂的调度(如果需要)等. 但是,有一个宏解决方案可以自动生成样板:https://github.com/mpilquist/simulacrum. 关于CsvEncoder示例的另一个重点是,instance是创建类型类实例的便捷方法,但apply是“召唤”(需要)这些实例的快捷方式.因此,第一个用于库扩展器(一种实现接口的方式),另一个用于用户(一种调用为该接口提供的特定操作的方法). (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |