如何调用使用 MTL 和 Parallel 的函数?
How to call a function which uses MTL and Parallel?
我正在使用 Parallel
类型 class 以收集所有验证错误:
def getNonEmptyStr[M[_]](key: String)(
implicit
E: MonadError[M, Errors],
A: ApplicativeAsk[M, Params],
W: FunctorTell[M, List[String]]
): M[String] = ???
def getInt[M[_]](key: String)(
implicit
E: MonadError[M, Errors],
A: ApplicativeAsk[M, Params],
W: FunctorTell[M, List[String]]
): M[Int] = ???
def getUser[M[_], F[_]](
implicit E: MonadError[M, Errors],
R: ApplicativeAsk[M, Params],
W: FunctorTell[M, List[String]],
P: Parallel[M, F]
): M[User] =
(getNonEmptyStr("name"), getInt("age"), getNonEmptyStr("address"))
.parMapN(User)
getUser
函数有两个类型参数:
M
是我的 monad 转换器堆栈,
F
是一些与 M
双重但允许并行执行的应用程序。
然后我想用下面的 monad 转换器堆栈调用它:
type Stack[A] = EitherT[WriterT[Reader[Params, ?], List[String], ?], Errors, A]
我需要指定 M
类型参数来告诉编译器我正在使用哪个堆栈。但是我还必须指定 F
参数:
getUser[Stack, Nested[WriterT[Reader[Params, ?], List[String], ?], Validated[Errors, ?], ?]].value.run.run(params)
这看起来很丑。有没有办法让编译器推断 F
?
完整代码在这里:https://gist.github.com/vkorenev/21bdd7d57e81a0752972f4bb3f45398a
尝试"partial application"
def getUser[M[_]](implicit E: MonadError[M, Errors],
R: ApplicativeAsk[M, Params],
W: FunctorTell[M, List[String]]
) = new GetUserHlp[M]
class GetUserHlp[M[_]](implicit E: MonadError[M, Errors],
R: ApplicativeAsk[M, Params],
W: FunctorTell[M, List[String]]
) {
def apply[F[_]](implicit P: Parallel[M, F]): M[User] =
(getNonEmptyStr("name"), getInt("age"), getNonEmptyStr("address"))
.parMapN(User)
}
getUser[Stack].apply.value.run.run(params)
或者创建类型class
trait GetUser[M[_]] {
def apply(): M[User]
}
object GetUser {
implicit def default[M[_], F[_]](implicit E: MonadError[M, Errors],
R: ApplicativeAsk[M, Params],
W: FunctorTell[M, List[String]],
P: Parallel[M, F]
): GetUser[M] = new GetUser[M] {
override def apply(): M[User] = (getNonEmptyStr("name"), getInt("age"), getNonEmptyStr("address"))
.parMapN(User)
}
}
def getUser[M[_]](implicit gu: GetUser[M]): M[User] = gu()
getUser[Stack].value.run.run(params)
可以使用 cats-par library or to add an auxiliary Parallel1
type class as suggested here。
那么getUser
只需要一个类型参数:
def getUser[M[_]](
implicit
E: MonadError[M, Errors],
R: ApplicativeAsk[M, Params],
W: FunctorTell[M, List[String]],
P: Parallel1[M]
): M[User] = {
import P._
(getNonEmptyStr("name"), getInt("age"), getNonEmptyStr("address")).parMapN(User)
}
希望将其中一个修复程序添加到 cats
。
我正在使用 Parallel
类型 class 以收集所有验证错误:
def getNonEmptyStr[M[_]](key: String)(
implicit
E: MonadError[M, Errors],
A: ApplicativeAsk[M, Params],
W: FunctorTell[M, List[String]]
): M[String] = ???
def getInt[M[_]](key: String)(
implicit
E: MonadError[M, Errors],
A: ApplicativeAsk[M, Params],
W: FunctorTell[M, List[String]]
): M[Int] = ???
def getUser[M[_], F[_]](
implicit E: MonadError[M, Errors],
R: ApplicativeAsk[M, Params],
W: FunctorTell[M, List[String]],
P: Parallel[M, F]
): M[User] =
(getNonEmptyStr("name"), getInt("age"), getNonEmptyStr("address"))
.parMapN(User)
getUser
函数有两个类型参数:
M
是我的 monad 转换器堆栈,F
是一些与M
双重但允许并行执行的应用程序。
然后我想用下面的 monad 转换器堆栈调用它:
type Stack[A] = EitherT[WriterT[Reader[Params, ?], List[String], ?], Errors, A]
我需要指定 M
类型参数来告诉编译器我正在使用哪个堆栈。但是我还必须指定 F
参数:
getUser[Stack, Nested[WriterT[Reader[Params, ?], List[String], ?], Validated[Errors, ?], ?]].value.run.run(params)
这看起来很丑。有没有办法让编译器推断 F
?
完整代码在这里:https://gist.github.com/vkorenev/21bdd7d57e81a0752972f4bb3f45398a
尝试"partial application"
def getUser[M[_]](implicit E: MonadError[M, Errors],
R: ApplicativeAsk[M, Params],
W: FunctorTell[M, List[String]]
) = new GetUserHlp[M]
class GetUserHlp[M[_]](implicit E: MonadError[M, Errors],
R: ApplicativeAsk[M, Params],
W: FunctorTell[M, List[String]]
) {
def apply[F[_]](implicit P: Parallel[M, F]): M[User] =
(getNonEmptyStr("name"), getInt("age"), getNonEmptyStr("address"))
.parMapN(User)
}
getUser[Stack].apply.value.run.run(params)
或者创建类型class
trait GetUser[M[_]] {
def apply(): M[User]
}
object GetUser {
implicit def default[M[_], F[_]](implicit E: MonadError[M, Errors],
R: ApplicativeAsk[M, Params],
W: FunctorTell[M, List[String]],
P: Parallel[M, F]
): GetUser[M] = new GetUser[M] {
override def apply(): M[User] = (getNonEmptyStr("name"), getInt("age"), getNonEmptyStr("address"))
.parMapN(User)
}
}
def getUser[M[_]](implicit gu: GetUser[M]): M[User] = gu()
getUser[Stack].value.run.run(params)
可以使用 cats-par library or to add an auxiliary Parallel1
type class as suggested here。
那么getUser
只需要一个类型参数:
def getUser[M[_]](
implicit
E: MonadError[M, Errors],
R: ApplicativeAsk[M, Params],
W: FunctorTell[M, List[String]],
P: Parallel1[M]
): M[User] = {
import P._
(getNonEmptyStr("name"), getInt("age"), getNonEmptyStr("address")).parMapN(User)
}
希望将其中一个修复程序添加到 cats
。