gpt4 book ai didi

scala - 在 Scala 中使用 Shapeless 折叠不同类型的列表

转载 作者:行者123 更新时间:2023-12-04 11:49:41 28 4
gpt4 key购买 nike

据我所知,shapeless 提供了 HList ( 异构 列表)类型,可以包含多种类型。

是否可以折叠HList ?例如,

// ref - Composable application architecture with reasonably priced monad
// code - https://github.com/stew/reasonably-priced/blob/master/src/main/scala/reasonable/App.scala

import scalaz.{Coproduct, Free, Id, NaturalTransformation}

def or[F[_], G[_], H[_]](f: F ~> H, g: G ~> H): ({type cp[α] = Coproduct[F,G,α]})#cp ~> H =
new NaturalTransformation[({type cp[α] = Coproduct[F,G,α]})#cp,H] {
def apply[A](fa: Coproduct[F,G,A]): H[A] = fa.run match {
case -\/(ff) ⇒ f(ff)
case \/-(gg) ⇒ g(gg)
}
}

type Language0[A] = Coproduct[InteractOp, AuthOp, A]
type Language[A] = Coproduct[LogOp, Language0, A]

val interpreter0: Language0 ~> Id = or(InteractInterpreter, AuthInterpreter)
val interpreter: Language ~> Id = or(LogInterpreter, interpreter0)


// What if we have `combine` function which folds HList
val interpreters: Language ~> Id = combine(InteractInterpreter :: AuthInterpreter :: LoginInterpreter :: HNil)

甚至,我可以简化 Langauge 的生成吗? ?
type Language0[A] = Coproduct[InteractOp, AuthOp, A]
type Language[A] = Coproduct[LogOp, Language0, A]

// What if we can create `Language` in one line
type Language[A] = GenCoproduct[InteractOp, AuthOp, LogOp, A]

最佳答案

为了一个完整的工作示例,假设我们有一些简单的代数:

sealed trait AuthOp[A]
case class Login(user: String, pass: String) extends AuthOp[Option[String]]
case class HasPermission(user: String, access: String) extends AuthOp[Boolean]

sealed trait InteractOp[A]
case class Ask(prompt: String) extends InteractOp[String]
case class Tell(msg: String) extends InteractOp[Unit]

sealed trait LogOp[A]
case class Record(msg: String) extends LogOp[Unit]

还有一些(毫无意义但可编译的)解释器:
import scalaz.~>, scalaz.Id.Id

val AuthInterpreter: AuthOp ~> Id = new (AuthOp ~> Id) {
def apply[A](op: AuthOp[A]): A = op match {
case Login("foo", "bar") => Some("foo")
case Login(_, _) => None
case HasPermission("foo", "any") => true
case HasPermission(_, _) => false
}
}

val InteractInterpreter: InteractOp ~> Id = new (InteractOp ~> Id) {
def apply[A](op: InteractOp[A]): A = op match {
case Ask(p) => p
case Tell(_) => ()
}
}

val LogInterpreter: LogOp ~> Id = new (LogOp ~> Id) {
def apply[A](op: LogOp[A]): A = op match {
case Record(_) => ()
}
}

此时您应该可以折叠 HList像这样的口译员:
import scalaz.Coproduct
import shapeless.Poly2

object combine extends Poly2 {
implicit def or[F[_], G[_], H[_]]: Case.Aux[
F ~> H,
G ~> H,
({ type L[x] = Coproduct[F, G, x] })#L ~> H
] = at((f, g) =>
new (({ type L[x] = Coproduct[F, G, x] })#L ~> H) {
def apply[A](fa: Coproduct[F, G, A]): H[A] = fa.run.fold(f, g)
}
)
}

但这不起作用的原因似乎与类型推断有关。不过,编写自定义类型类并不太难:
import scalaz.Coproduct
import shapeless.{ DepFn1, HList, HNil, :: }

trait Interpreters[L <: HList] extends DepFn1[L]

object Interpreters {
type Aux[L <: HList, Out0] = Interpreters[L] { type Out = Out0 }

implicit def interpreters0[F[_], H[_]]: Aux[(F ~> H) :: HNil, F ~> H] =
new Interpreters[(F ~> H) :: HNil] {
type Out = F ~> H
def apply(in: (F ~> H) :: HNil): F ~> H = in.head
}

implicit def interpreters1[F[_], G[_], H[_], T <: HList](implicit
ti: Aux[T, G ~> H]
): Aux[(F ~> H) :: T, ({ type L[x] = Coproduct[F, G, x] })#L ~> H] =
new Interpreters[(F ~> H) :: T] {
type Out = ({ type L[x] = Coproduct[F, G, x] })#L ~> H
def apply(
in: (F ~> H) :: T
): ({ type L[x] = Coproduct[F, G, x] })#L ~> H =
new (({ type L[x] = Coproduct[F, G, x] })#L ~> H) {
def apply[A](fa: Coproduct[F, G, A]): H[A] =
fa.run.fold(in.head, ti(in.tail))
}
}
}

然后你可以写你的 combine :
def combine[L <: HList](l: L)(implicit is: Interpreters[L]): is.Out = is(l)

并使用它:
type Language0[A] = Coproduct[InteractOp, AuthOp, A]
type Language[A] = Coproduct[LogOp, Language0, A]

val interpreter: Language ~> Id =
combine(LogInterpreter :: InteractInterpreter :: AuthInterpreter :: HNil)

您也许可以获得 Poly2版本工作,但这个类型类对我来说可能足够简单。不幸的是,您将无法简化 Language 的定义。但是,以您想要的方式键入别名。

关于scala - 在 Scala 中使用 Shapeless 折叠不同类型的列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33971404/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com