不成形的+;ScalaZ:在应用程序生成器中跟踪返回类型
根据@TravisBrown之前的博文,这是一个关于@TravisBrown的问题 由于遗留代码库的原因,我在这里非常痛苦地概述了它,因此在构建应用程序链时,我需要使用字符串键标记验证。希望我没有把事情搞得太复杂,我已经把博客文章的版本改成了Shapess 2,但是很不幸的是,我没有把我需要的东西简单地分离出来 我认为基本技巧是简单地重复使用链中的第一个不成形的+;ScalaZ:在应用程序生成器中跟踪返回类型,scala,scalaz,shapeless,Scala,Scalaz,Shapeless,根据@TravisBrown之前的博文,这是一个关于@TravisBrown的问题 由于遗留代码库的原因,我在这里非常痛苦地概述了它,因此在构建应用程序链时,我需要使用字符串键标记验证。希望我没有把事情搞得太复杂,我已经把博客文章的版本改成了Shapess 2,但是很不幸的是,我没有把我需要的东西简单地分离出来 我认为基本技巧是简单地重复使用链中的第一个ApplicationBuilder,然后通过一次展开一个嵌套来展开结果,从(D,(C,(B,A))=>(A,B,C,D) 我如何重复使用它来执
ApplicationBuilder
,然后通过一次展开一个嵌套来展开结果,从(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)
}
包测试{
类型ErrorsOr[A]=ValidationNel[String,A]
类型nestederror[T]=ValidationNel[(字符串,字符串),T]
类型验证程序[A]=String=>ErrorsOr[A]
隐式类VdNelAug[T](val vd:ErrorsOr[T])扩展了AnyVal{
def标签(键:字符串):WrappedValidation[T]=新WrappedValidation[T](键,vd.leftMap(
nel=>nel.map(值=>key->value))
)
}
}
类WrappedValidation[T](val prop:String,val validation:nestederror[T]){
def和[A](wv:WrappedValidation[A]):ValidationBuilder[
NestedErrorsOr[T]::NestedErrorsOr[A]::HNil,
T::A::HNil]={
//我不知道如何推断这里的类型。
新的ValidationBuilder(
列表(wv.prop,prop),
验证(wv.验证)
)
}
}
类验证生成器[
Valr],F[H]](
(f,fa)=>fa.map(hf=>(h:h)=>(t:t)=>hf(h::t))
)
}
我猜这个技巧是示例中多边形和文件夹的组合,但我不明白为什么提供的F[\u]
是必要的,因为我们可以通过使用hlist链预测应用的类型,我们可以从验证本身的类型参数创建。我所说的F[\u]
不是指Poly
中的那一个,而是指用于推导正确验证的那一个
该函数不能是任意的In=>Out
,其中In
与未包装验证的类型相同吗
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))
)
}