在无形副产品上进行模式匹配的简洁方法
Clean way of doing Pattern matching on shapeless Coproduct
我发现了两种可以对无形余积进行模式匹配的方法。我还用谷歌搜索了这个主题,发现 this
import shapeless._
object ShapelessEx3 extends App {
case class Red()
case class Green()
case class Blue()
type Colors = Red :+: Green :+: Blue :+: CNil
val blue = Coproduct[Colors](Blue())
val green = Coproduct[Colors](Green())
printColor1(blue)
printColor2(green)
def printColor1(c: Colors) : Unit = {
(c.select[Red], c.select[Green], c.select[Blue]) match {
case (Some(_), None, None) => println("Color is red")
case (None, Some(_), None) => println("Color is green")
case (None, None, Some(_)) => println("Color is blue")
case _ => println("unknown color")
}
}
def printColor2(c: Colors) : Unit = {
c match {
case Inl(Red()) => println("color is red")
case Inr(Inl(Green())) => println("color is green")
case Inr(Inr(Inl(Blue()))) => println("color is blue")
case _ => println("unknown color")
}
}
}
但是这两个函数都非常嘈杂,如 case (None, Some(_), None)
或 Inr(Inr(Inl(Blue())))
。我怎样才能像
这样简单的模式匹配
c match {
case Red() =>
case Green() =>
case Blue() =>
}
你可以使用 Poly1 例如
import shapeless._
case class Red()
case class Green()
case class Blue()
type Colors = Red :+: Green :+: Blue :+: CNil
val blue = Coproduct[Colors](Blue())
val green = Coproduct[Colors](Green())
object printColor extends Poly1 {
implicit def caseRed = at[Red] {r=> println("red") ;r }
implicit def caseBlue = at[Blue]{b=> println("blue");b }
implicit def caseGreen= at[Green]{g =>println("green");g }
}
green map printColor
blue map printColor
只是扩展了之前的答案。 Coproduct#fold
方法更等同于匹配大小写功能。
import shapeless._
case class Red()
case class Green()
case class Blue()
type Colors = Red :+: Green :+: Blue :+: CNil
val blue = Coproduct[Colors](Blue())
object printColor extends Poly1 {
implicit def caseRed = at[Red](red => println("red"))
implicit def caseBlue = at[Blue](blue => println("blue"))
implicit def caseGreen = at[Green](green => println("green"))
}
// This is equivalent to a match - case block
val printBlueResult: Unit = blue.fold(printColor)
object mapColor extends Poly1 {
implicit def caseRed = at[Red](red => 1)
implicit def caseBlue = at[Blue](blue => "a")
implicit def caseGreen = at[Green](green => true)
}
// This maps the Coproduct to a new Coproduct
val mapBlueResult: Int :+: Boolean :+: String :+: CNil = blue.map(mapColor)
我发现了两种可以对无形余积进行模式匹配的方法。我还用谷歌搜索了这个主题,发现 this
import shapeless._
object ShapelessEx3 extends App {
case class Red()
case class Green()
case class Blue()
type Colors = Red :+: Green :+: Blue :+: CNil
val blue = Coproduct[Colors](Blue())
val green = Coproduct[Colors](Green())
printColor1(blue)
printColor2(green)
def printColor1(c: Colors) : Unit = {
(c.select[Red], c.select[Green], c.select[Blue]) match {
case (Some(_), None, None) => println("Color is red")
case (None, Some(_), None) => println("Color is green")
case (None, None, Some(_)) => println("Color is blue")
case _ => println("unknown color")
}
}
def printColor2(c: Colors) : Unit = {
c match {
case Inl(Red()) => println("color is red")
case Inr(Inl(Green())) => println("color is green")
case Inr(Inr(Inl(Blue()))) => println("color is blue")
case _ => println("unknown color")
}
}
}
但是这两个函数都非常嘈杂,如 case (None, Some(_), None)
或 Inr(Inr(Inl(Blue())))
。我怎样才能像
c match {
case Red() =>
case Green() =>
case Blue() =>
}
你可以使用 Poly1 例如
import shapeless._
case class Red()
case class Green()
case class Blue()
type Colors = Red :+: Green :+: Blue :+: CNil
val blue = Coproduct[Colors](Blue())
val green = Coproduct[Colors](Green())
object printColor extends Poly1 {
implicit def caseRed = at[Red] {r=> println("red") ;r }
implicit def caseBlue = at[Blue]{b=> println("blue");b }
implicit def caseGreen= at[Green]{g =>println("green");g }
}
green map printColor
blue map printColor
只是扩展了之前的答案。 Coproduct#fold
方法更等同于匹配大小写功能。
import shapeless._
case class Red()
case class Green()
case class Blue()
type Colors = Red :+: Green :+: Blue :+: CNil
val blue = Coproduct[Colors](Blue())
object printColor extends Poly1 {
implicit def caseRed = at[Red](red => println("red"))
implicit def caseBlue = at[Blue](blue => println("blue"))
implicit def caseGreen = at[Green](green => println("green"))
}
// This is equivalent to a match - case block
val printBlueResult: Unit = blue.fold(printColor)
object mapColor extends Poly1 {
implicit def caseRed = at[Red](red => 1)
implicit def caseBlue = at[Blue](blue => "a")
implicit def caseGreen = at[Green](green => true)
}
// This maps the Coproduct to a new Coproduct
val mapBlueResult: Int :+: Boolean :+: String :+: CNil = blue.map(mapColor)