2017-11-23 5 views
0

最初の行にタイプ注釈を追加する必要があるのはなぜですか? c.get[List[String]]("primary-group")は、それがトップタイプを維持し、Decoder.Result[String]あるべきflatMapDecoder.Result[List[String]]ですが、それはどちらか[DecodingFailure、文字列]に変更されます。どうして?問題はそれがdependent typeですか? : Decoder.Result[StringなしflatMapを使用したタイプの解像度

case class JWTPayload(primaryGroup: Group, groupMember: List[Group], name: String, pid: String) 

    implicit val jwtPayloadDecoder: Decoder[JWTPayload] = Decoder.instance(c => 
    (
     c.get[List[String]]("primary-group").flatMap(l => if(l.size == 1) l.head.asRight else DecodingFailure("", c.history).asLeft) : Decoder.Result[String], 
     c.get[List[String]]("group-member"), 
     c.get[String]("name"), 
     c.get[String]("pid") 
    ).map4(
    JWTPayload 
    ) 
) 

私はこれがフル答えではないが、私はそれはいくつかの洞察を提供することを願っています

Error:(43, 7) value map4 is not a member of (scala.util.Either[io.circe.DecodingFailure,String], io.circe.Decoder.Result[List[String]], io.circe.Decoder.Result[String], io.circe.Decoder.Result[String]) 
possible cause: maybe a semicolon is missing before `value map4'? 
    ).map4(

おかげ

答えて

1

を取得します。ここで重要な部分は、map4の実装方法です。ネコ0.9のように、それは(ネコ1.0で「デカルト」が「semigroupal」に変更した)cats.syntax.Tuple4CartesianOpsクラスに4タプルをラップcats.syntax.TupleCartesianSyntax形質その暗黙catsSyntaxTuple4Cartesianを介して行われます。このコードは、最大22のタプルすべてに対してBoilerplate.scalaによって自動生成されます。

implicit def catsSyntaxTuple4Cartesian[F[_], A0, A1, A2, A3](t4: Tuple4[F[A0], F[A1], F[A2], F[A3]]): Tuple4CartesianOps[F, A0, A1, A2, A3] = new Tuple4CartesianOps(t4) 


private[syntax] final class Tuple4CartesianOps[F[_], A0, A1, A2, A3](t4: Tuple4[F[A0], F[A1], F[A2], F[A3]]) { 
    def map4[Z](f: (A0, A1, A2, A3) => Z)(implicit functor: Functor[F], cartesian: Cartesian[F]): F[Z] = Cartesian.map4(t4._1, t4._2, t4._3, t4._4)(f) 
    def contramap4[Z](f: Z => (A0, A1, A2, A3))(implicit contravariant: Contravariant[F], cartesian: Cartesian[F]): F[Z] = Cartesian.contramap4(t4._1, t4._2, t4._3, t4._4)(f) 
    def imap4[Z](f: (A0, A1, A2, A3) => Z)(g: Z => (A0, A1, A2, A3))(implicit invariant: Invariant[F], cartesian: Cartesian[F]): F[Z] = Cartesian.imap4(t4._1, t4._2, t4._3, t4._4)(f)(g) 
    def apWith[Z](f: F[(A0, A1, A2, A3) => Z])(implicit apply: Apply[F]): F[Z] = apply.ap4(f)(t4._1, t4._2, t4._3, t4._4) 
} 

注意F[_](ファンクタ)のパラメータを入力します。自動生成されたコードは次のようになります。効果的にこのコードでは、各内部型がいくつかの型の上で同じファンクタである4タプルにmap4メソッドを追加しています。あなたがDecoder.Result[String]を指定しない場合は、Scalaのコンパイラはそれが必要があることを取得するのに十分にスマートではありません

cats.implicits.catsSyntaxTuple4Cartesian[Decoder.Result, String, List[String], String, String](
    c.get[List[String]]("primary-group").flatMap(l => if (l.size == 1) l.head.asRight else DecodingFailure("", c.history).asLeft): Decoder.Result[String], 
    c.get[List[String]]("group-member"), 
    c.get[String]("name"), 
    c.get[String]("pid") 
).map4[JWTPayload](
    JWTPayload 
) 

:だから(部分)暗黙の解像度あなたのコードは、実際にこのようなものになった後、あなたが、import cats.implicits._をしたと仮定し

FunctorCartesian暗黙オブジェクトが一致する

  • ファンクタ型Either[DecodingFailure, _]StringEither[DecodingFailure, String]を分割した後

    1. それはタプル内の他の3つのフィールドに使用ファンクタタイプにマッチする(実際cats.instances.AllInstancescats.instances.EitherInstances形質介しcats.implicitsオブジェクトによって提供される)(すなわちDecoder.Result[_])。

    だから私は、この動作が暗黙のオプス・クラスを経由してmap4が4組に追加されているという事実と、基になる型は、一般的な2ヶ所であるEitherであるという事実の組み合わせの結果だと思います単純なFunctorではなくタイプです。

  • +0

    私はヴァル 私は タイプの結果を持っている場合は、[A] =いずれかの[DecodingFailure、A]ということである奇妙な行動:私は書いていない[文字列] =右( "123")結果 //入力はいずれかである[DecodingFailure、INT] ヴァルdefaultTypeInference = a.map(Integer.parseInt) // [INT] ヴァルcoercedToBeResult結果であると強制:結果[INT] = a.map(Integer.parseInt) を この場合のflatMapのマップがResult型を保持しないのはなぜですか?私はこれがタイプエイリアスではないことを知っていますが、とにかく – user1698641

    +0

    @ user1698641、私はあなたの意見を得るのか分かりません。私が 'c.get [String](" name ")のように' map'を使用するものに3行目を変更した場合。map(x => x + x) 'の場合、明示的な型ヒント' Decoder.Result [String] 'を指定しないかぎり、コンパイルも停止します。このシナリオの問題は、 'flatMap'を実行したときに型が失われるということではありません。 'Result [A]'と 'DecodingFailure、A 'の型はまったく同じで、Scalaコンパイラはそれを知っています。問題は、 'Decoder.Result [_]'に '_ [_、_]'型のこの自明でない** _ split _ **が失われ、Scalaコンパイラがそれ自身で再作成するのに十分スマートではないということです。 – SergGr

    関連する問題