如何从实现类型类的元组中提取类型 [英] How to extract types from a tuple that implements a typeclass

查看:52
本文介绍了如何从实现类型类的元组中提取类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

函数a可以接收单个参数或元组,这些参数必须是StringIdentifiable类型类的成员

Function a can receive single argument or a tuple, these arguments need to be members of typeclass StringIdentifiable

如何将元组类型提取和分解为也具有typeclass实例的类型

How to extract and decompose tuple type into types that also have instances of the typeclass

@typeclass trait StringIdentifiable[M] {
  def identify(id: M): String
}

def a[K: StringIdentifiable] (k:K){
 k match{
case (k1) => 
 implicitly[StringIdentifiable[K]].identify(k1)
case (k1,k2) =>
 implicitly[StringIdentifiable[k1.type]].identify(k1) 
 implicitly[StringIdentifiable[k2.type]].identify(k2)
}

第二场比赛我出错:

Could not find an instance of StringIdentifiable for k1.type

推荐答案

您可以无形地做到这一点.例如:

You can do this with shapeless. For instance:

import shapeless._, ops.hlist._

object MyPoly extends Poly2 { 
  implicit def foo[A] = at[A, StringIdentifiable[A]]( (a, f) => f.identify(a) ) 
}

def a[K: StringIdentifiable, L <: HList, O <: HList](k: K)(
  implicit 
  gen: Generic.Aux[K, L], // decompose K into HList L
  lift: LiftAll.Aux[StringIdentifiable, L, O], // find an instance of StringIdentifiable for every element of L
  zip: ZipWith[L, O, MyPoly.type] // zip L with its typeclass instances and map the results with the polymorphic function MyPoly
): String :: zip.Out = { 
  val l = gen.to(k)
  val o = lift.instances
  implicitly[StringIdentifiable[K]].identify(k) :: zip(l, o) 
}

implicit def id1[A,B]: StringIdentifiable[(A, B)] = _ => "1"
implicit val id2: StringIdentifiable[String] = _ => "2"
implicit val id3: StringIdentifiable[Int] = _ => "3"

a(("foo", 42)) // 1 :: 2 :: 3 :: HNil

要完全解决您的问题(IIUC),可能需要使用Shapeless为所有元组自动生成 StringIdentifiable 实例.

A full solution to your problem (IIUC) probably consists of using shapeless to automatically generate StringIdentifiable instances for all tuples.

trait StringIdentifiable[M] {
  def identify(id: M): String
}
object StringIdentifiable {
  object MyPoly extends Poly2 { 
     implicit def foo[A] = at[A, StringIdentifiable[A]]( (a, f) => f.identify(a) ) 
  }

  implicit def mkSI[K, L <: HList, O <: HList](
    implicit
    tup: IsTuple[K],
    gen: Generic.Aux[K, L],
    lift: LiftAll.Aux[StringIdentifiable, L, O],
    zip: ZipWith[L, O, MyPoly.type]
  ): StringIdentifiable[K] = { 
    val o = lift.instances
    k => {
      val l = gen.to(k)
      zip(l, o).mkString("(", ", ", ")")
    }
  }
}

这篇关于如何从实现类型类的元组中提取类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆