scala - Creating a type class instance for a sealed trait -


say have 'wide' sealed class hierarchy:

sealed trait alphabet case class a(word: string) extends alphabet ... case class z(word: string) extends alphabet 

and have type class instance defined each child class in hierarchy:

trait swearwordfinder[t <: alphabet] {   def isswearword(x: t): boolean }  val swearwordfindera = new swearwordfinder[a] { ... } ... val swearwordfinderz = new swearwordfinder[z] { ... } 

is there way can define type class instance alphabet trait without having implement pattern matching (as below)?

def isswearword(x: alphabet): boolean = x match {   case a: => swearwordfindera.isswearword(a)   ...   case z: z => swearwordfinderz.isswearword(z) } 

you can represent alphabet shapeless coproduct of a :+: b :+: ... :+: z :+: cnil, if have swearwordfinder instances a, b, ... , define instances cnil , :+: can swearwordfinder[alphabet] using generic representation.

import shapeless._  trait swearwordfinder[t] {   def isswearword(x: t): boolean }  object swearwordfinder extends swearwordfinder0 {   implicit def apply[t](implicit swf: swearwordfinder[t]): swearwordfinder[t] = swf    implicit val cnilswearwordfinder: swearwordfinder[cnil] =      new swearwordfinder[cnil] {       def isswearword(t: cnil): boolean = false     }    implicit def coproductconsswearwordfinder[l, r <: coproduct](implicit      lswf: swearwordfinder[l],      rswf: swearwordfinder[r]   ): swearwordfinder[l :+: r] =      new swearwordfinder[l :+: r] {       def isswearword(t: l :+: r): boolean =          t.eliminate(lswf.isswearword, rswf.isswearword)     } }  trait swearwordfinder0 {   implicit def genericswearwordfinder[t, g](implicit      gen: generic.aux[t, g],     swf: lazy[swearwordfinder[g]]   ): swearwordfinder[t] =     new swearwordfinder[t] {       def isswearword(t: t): boolean = swf.value.isswearword(gen.to(t))     } } 

now instances our letters :

sealed trait alphabet extends product serializable  object alphabet {   final case class a(word: string) extends alphabet   final case class z(word: string) extends alphabet }  implicit val swfa = new swearwordfinder[alphabet.a] {   def isswearword(a: alphabet.a) = a.word == "apple" }  implicit val swfz = new swearwordfinder[alphabet.z] {   def isswearword(z: alphabet.z) = z.word == "zebra" } 

and can swearwordfinder[alphabet] :

def isbadword[t](t: t)(implicit swft: swearwordfinder[t]): boolean =    swft.isswearword(t)  val a1: alphabet = alphabet.a("apple") val z2: alphabet = alphabet.z("zorro") val z3: alphabet = alphabet.z("zebra")  isbadword(a1) // true isbadword(z2) // false isbadword(z3) // true 

like mentioned in comment: beware of si-7046. alphabet ast needs in project on project swearwordfinder depends or in package compiled before package type class derivation alphabet.


Comments

Popular posts from this blog

sql - invalid in the select list because it is not contained in either an aggregate function -

Angularjs unit testing - ng-disabled not working when adding text to textarea -

How to start daemon on android by adb -