首页 > 解决方案 > 在状态单子中使用 flatMap 映射时类型推断失败

问题描述

概述

我试图推断cats.data.IndexedStateT[F[_], SA, SB, A]传入 flatMap 方法的类型。仅使用 flatMap 时,类型推断似乎可以正确推断 SA、SB 和 A 的类型参数。但是,当我在 flatMap 中使用 map 时,它会失败。

有没有办法在不手动指定传递给 flatMap 的 IndexedStateT 的类型参数的情况下使这种类型推断工作?

class X
class Y


// Type inference works well when just using flatMap
val res1: IndexedStateT[Eval, Unit, Y, Y] =
    IndexedStateT[Eval, Unit, X, X](_ => Eval.now(new X, new X))
      .flatMap { x =>
        IndexedStateT(_ => Eval.now(new Y, new Y)) // Infers IndexedStateT[Eval, X, Y, Y]
      }


// Type inference fails when mapping inside flatMap
val res2: IndexedStateT[Eval, Unit, Y, (X, Y)] =
    IndexedStateT[Eval, Unit, X, X](_ => Eval.now(new X, new X))
      .flatMap { x =>
        IndexedStateT(_ => Eval.now(new Y, new Y)).map(x -> _) // Fails to infer the types for IndexedStateT[Eval, X, Y, Y] "missing parameter type"
      }

使用上下文

我在应用程序代码中使用了一种特殊类型的 State monad

type HListState[SA <: HList, A] = IndexedStateT[Eval, SA, A :: SA, A]
  object HListState {
    def apply[SA <: HList, A](fn: SA => A): HListState[SA, A] = IndexedStateT[Eval, SA, A :: SA, A](sa => Eval.now((fn(sa) :: sa, fn(sa))))
  }

// Type inference works here
val res3: IndexedStateT[Eval, HNil, Y :: X :: HNil, Y] =
  HListState[HNil, X](_ => new X).flatMap { x =>
    HListState(_ => new Y)
  }

// Inference not so good :(
val res4: IndexedStateT[Eval, HNil, Y :: X :: HNil, (X, Y)] = 
  HListState[HNil, X](_ => new X).flatMap { x =>
    HListState(_ => new Y).map(x -> _)  // <--- type inference fails here :( "missing parameter type"
  }

有没有办法让类型推断在这种情况下工作?

标签: scalashapelessscala-cats

解决方案


如果没有map,编译器可以使用预期的类型res1来计算 的类型参数flatMap等等IndexedStateT。但是,当您添加 时map,呼叫没有预期的类型IndexedStateT

如果不进行测试,我无法确定,但我希望指定参数类型 ( SA) 就足够了,其余的应该可以毫无问题地推断出来:

IndexedStateT { _: X => Eval.now(new Y, new Y) }.map(x -> _)

推荐阅读