使用较长的隐式参数列表清理签名 [英] Clean up signatures with long implicit parameter lists

查看:97
本文介绍了使用较长的隐式参数列表清理签名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否存在一种优雅的解决方案,以某种方式清理隐式参数列表,使签名更加简洁? 我有这样的代码:

Is there an elegant solution to somehow clean up implicit parameter lists making signatures more concise? I have code like this:

import shapeless._
import shapeless.HList._
import shapeless.ops.hlist._
import shapeless.poly._

trait T[I, O] extends (I => O)

trait Validator[P]

object Validator{
  def apply[P] = new Validator[P]{}
}

object valid extends Poly1 {
  implicit def caseFunction[In, Out] = at[T[In, Out]](f => Validator[In])
}

object isValid extends Poly2 {
  implicit def caseFolder[Last, New] = at[Validator[Last], T[Last, New]]{(v, n) => Validator[New]}
}

object mkTask extends Poly1 {
  implicit def caseT[In, Out] = at[T[In, Out]](x => x)
  implicit def caseFunction[In, Out] = at[In => Out](f => T[In, Out](f))
}

object Pipeline {

  def apply[H <: HList, Head, Res, MapRes <: HList](steps: H)
       (implicit
        mapper: Mapper.Aux[mkTask.type,H, MapRes],
        isCons: IsHCons.Aux[MapRes, Head, _],
        cse: Case.Aux[valid.type, Head :: HNil, Res],
        folder: LeftFolder[MapRes, Res, isValid.type]
         ): MapRes = {
    val wrapped = (steps map mkTask)
    wrapped.foldLeft(valid(wrapped.head))(isValid)
    wrapped
  }
}

// just for sugar
def T[I, O](f: I => O) = new T[I, O] {
  override def apply(v1: I): O = f(v1)
}

Pipeline(T((x:Int) => "a") :: T((x:String) => 5) :: HNil) // compiles OK
Pipeline(((x:Int) => "a") :: ((x:String) => 5) :: HNil) // compiles OK

// Pipeline("abc" :: "5" :: HNil) // doesn't compile
// can we show an error like "Parameters are not of shape ( _ => _ ) or T[_,_]"?

//  Pipeline(T((x: Int) => "a") :: T((x: Long) => 4) :: HNil) // doesn't compile
// can we show an error like "Sequentiality constraint failed"?

我还想添加一些对于库功能必需的隐式参数(到Pipeline.apply方法中),但是签名已经很大.我担心其他开发人员难以理解-是否有最佳实践"方式来构造这些参数?

And I also want to add a couple of implicit params necessary for the library's functionality (to the Pipeline.apply method), but the signature is already huge. I am worried about the ease of understanding for other developers - is there a "best practice" way to structure these params?

我的意思是隐式参数分为不同的类别.在此示例中:mapper确保适当的内容类型,isConscsefolder确保对输入的顺序约束,我想添加表示业务逻辑可操作性"的隐式.应该如何对它们进行分组,是否可以采用可读格式?

What I mean is the implicit parameters fall into different categories. In this example: mapper ensures proper content types, isCons, cse and folder ensure a sequential constraint on input, and I would like to add implicits representing "doability" of the business logic. How should they be grouped, is it possible to do in a readable format?

Edit2:是否可以以某种方式向库用户发出关于违反哪个约束的警报?例如.是HList中的类型错误,还是没有保持顺序约束,或者他缺少适当的业务逻辑"隐式?

Would it be possible to somehow alert the library's user, as to which constraint is violated? E.g. either the types in the HList are wrong, or the sequentiality constraint is not held, or he lacks the proper "business logic" implicits?

推荐答案

我的建议是使用包含该配置的隐式案例类:

My suggestion was to use an implict case class that contains that configuration:

case class PipelineArgs(mapper: Mapper.Aux[mkTask.type,H, MapRes] = DEFAULTMAPPER,
  isCons: IsHCons.Aux[MapRes, Head, _] = DEFAULTISCON,
  cse: Case.Aux[valid.type, Head :: HNil, Res] = DEFAULTCSE,
  folder: LeftFolder[MapRes, Res, isValid.type] = DEFAULTFOLDER) {
    require (YOUR TESTING LOGIC, YOUR ERROR MESSAGE)
  } 

object Pipeline {
  def apply[H <: HList, Head, Res, MapRes <: HList](steps: H)
  (implicit args:PipelineArgs)  = {
     val wrapped = (steps map mkTask)
     wrapped.foldLeft(valid(wrapped.head))(isValid)
     wrapped
  }

这并没有多大帮助.清晰(但不要担心,我看得更糟),但是它可以帮助通知用户他正在创建args实例时搞砸了a)将默认值放入CClass构造函数中缺少的参数b)放许多"require"子句.

It doesn't help much w.r.t. clarity (but don't worry, I have seen worse), but it helps at notifying the user he's messing up at the creation of the args instance as you can a) put default values to the missing arguments in the CClass constructor b) put a number of "require" clauses.

这篇关于使用较长的隐式参数列表清理签名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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