Ограничение на уровне типа в HList, извлечение функциональной области - PullRequest
2 голосов
/ 28 июня 2019

Я пишу комбинатор, который принимает HList из Option[A] :: Option[AA] :: Option[AAA]... и т. Д.

Также принимает функцию f типа A,AA, AAA,... => U. И это возвращает U. Как мне кодировать сигнатуру типа для моего комбинатора? Я должен предположить, что мои A, AA, AAA также являются моноидами, поэтому, если мои параметры None, я могу вызвать моноидный ноль для создания значений для f. Я новичок в бесформенном, так что спасибо!

Это то, что я имею до сих пор, но мне не хватает многих ограничений.

  1. Каждый элемент H является Option[A], Option[AA], ...
  2. A, AA, AAA все моноиды.
  3. HList D - это просто такой же как H без опции.
def combinator[H <: HList, D <: HList, U](in: H, f : D => U) : U =
  f(in map { 
    case None : Option[A] => implicitly[Monoid[A]].zero
    case Some(v) => v
  })

1 Ответ

2 голосов
/ 29 июня 2019

Попробуйте

  import shapeless.{HList, ::, HNil, Id, Poly1}
  import shapeless.ops.hlist.{Comapped, LiftAll, Mapper, NatTRel}
  import cats.Monoid
  import cats.syntax.option._
  import cats.instances.int._
  import cats.instances.string._
  import cats.instances.double._

  object monoidPoly extends Poly1 {
    implicit def cse[A: Monoid]: Case.Aux[Option[A], A] = at {
      case None => implicitly[Monoid[A]].empty
      case Some(v) => v
    }
  }

  def combinator[H <: HList, D <: HList, U](in: H, f: D => U)(
    implicit
//    comapped: Comapped.Aux[H, Option, D],
//    natTRel: NatTRel[H, Option, D, Id],
//    liftAll: LiftAll[Monoid, D],
    mapper: Mapper.Aux[monoidPoly.type, H, D]
  ): U =
    f(in map monoidPoly)

  combinator(1.some :: none[String] :: 2.0.some :: HNil, (_ : Int :: String :: Double :: HNil).toString)
  // "1 ::  :: 2.0 :: HNil"
...