Shapeless + ScalaZ:跟踪应用程序构建器内的返回类型

时间:2016-06-11 23:53:27

标签: scala scalaz shapeless

@TravisBrown的问题主要基于他之前的博文here

由于遗留代码库的原因,我非常痛苦地在这里概述,我需要在构建应用程序链时用字符串键标记验证。为了避免让事情变得过于复杂,我已经将博客文章版本改编为Shapeless 2,但却没有惨淡地将我需要的那些内容简单地分离出来。

我认为潜在的诀窍是简单地重复使用链中的第一个ApplicativeBuilder,然后解开结果,从(D, (C, (B, A))) => (A, B, C, D)开始,一次解开一个嵌套。

如何重复使用它来执行以下操作:

    package test {
      type ErrorsOr[A] = ValidationNel[String, A]
      type NestedErrorsOr[T] = ValidationNel[(String, String), T]
      type Validator[A] = String => ErrorsOr[A]

      implicit class VdNelAug[T](val vd: ErrorsOr[T]) extends AnyVal {
        def label(key: String): WrappedValidation[T] = new WrappedValidation[T](key, vd.leftMap(
          nel => nel.map(value => key -> value))
        )
      }
    }



class WrappedValidation[T](val prop: String, val validation: NestedErrorsOr[T]) {

    def and[A](wv: WrappedValidation[A]): ValidationBuilder[
      NestedErrorsOr[T] :: NestedErrorsOr[A] :: HNil,
      T :: A :: HNil] = {

      // I don't know how to infer the type here.
      new ValidationBuilder(
        List(wv.prop, prop),
        validation |@| wv.validation)
      )
    }
  }
class ValidationBuilder[
  ValTypes <: HList,
  ArgTypes <: HList,
  BuilderType = ???
](builder: BuilderType?): {

def apply[V, Ret, Rev <: Hlist, Args <: HList](fn: V => Ret)(
   implicit rev: Reverse.Aux[ArgTypes, Rev]
     tupler: Tupler.Aux[Rev, Args],
     ev: Args =:= V
): Either[CustomError, Ret] = {
   // ingnore the custom conversion of the nel, this is just about
   // performing a simple groupBy the label such as all the error messages
   // For a given label are returned under the same key.
   builder.fold(nel => nel.toCustom, fn)
}

我相信我得到了原则,但差距来自缺乏无形API体验。

object Applier extends Poly2 {
    implicit def ap[F[_]: Applicative, H, T <: HList, R]:
    Case2.Aux[Applier.type, F[(H :: T) => R], F[H], F[T => R]] =
      at[F[(H :: T) => R], F[H]](
        (f, fa) => fa <*> f.map(hf => (h: H) => (t: T) => hf(h :: t))
      )
  }

我猜这个技巧是示例中的poly和文件夹的组合,但是我不明白为什么提供的F[_]是必要的,因为我们可以预测它的类型通过使用hlist链来应用我们可以从验证本身的类型参数创建。 F[_]我不是指Poly中的那个,而是用于推导正确验证的那个。

这个函数不能只是一个In => Out,其中In与解包验证的类型相同吗?

0 个答案:

没有答案