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

How to start daemon on android by adb -

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

testing - Detect whether test has failed within fixture -