【问题标题】:Type mismatch during refactoring using Slick使用 Slick 重构期间的类型不匹配
【发布时间】:2016-04-22 07:23:11
【问题描述】:

我想要制作 DRYer 的以下代码:

def createAdmin(/* ... */): Future[Int] =
  db.run {
    {
      (users returning users.map(_.id)) += Account(0, /* ... */)
    } flatMap { id =>
      admins += Admin(userId = id, /* ... */)
    }
  }

def createStandardUser(/* ... */): Future[Int] =
  db.run {
    {
      (users returning users.map(_.id)) += Account(0, /* ... */)
    } flatMap { id =>
      standardUsers += StandardUser(userId = id, /* ... */)
    }
  }

编译得很好。但是,如果我将两者合并为以下内容:

def createUser(role: String)(/* ... */): Future[Int] =
  db.run {
    {
      (users returning users.map(_.id)) += Account(0, /* ... */)
    } flatMap { id =>
      role match {
        case "admin" =>
          admins += Admin(userId = id, /* ... */)
        case "standard" =>
          standardUsers += StandardUser(userId = id, /* ... */)
      }
    }
  }

我收到以下类型不匹配错误:

[error]  found   : Long => slick.dbio.DBIOAction[Int,slick.dbio.NoStream,Nothing]
[error]  required: Long => slick.dbio.DBIOAction[Int,slick.dbio.NoStream,E2]
[error]       } flatMap { id =>
[error]                      ^
[error] one error found

我似乎无法弄清楚为什么。有人可以帮我解释一下吗?

【问题讨论】:

    标签: scala slick


    【解决方案1】:

    编译器无法正确判断使用的效果类型。作为一种解决方法,您应该能够通过指定使用的类型来给它一些帮助,例如在 flatMap 操作中,这将是

    flatMap[Int, NoStream, Effect.Write] { id => 
    

    在你的情况下。

    【讨论】:

    • 这行得通!或者,如果不需要返回类型(我就是这种情况),可以将 flatMap[...] 替换为 map 并将方法的返回类型更改为 Future[Unit]
    【解决方案2】:

    恐怕你不能那样重构代码。 我知道从代码的角度来看它看起来很合理。但是flatMap 中的模式匹配并没有为编译器提供足够的信息来推断effectDBIOAction

    正如您在source code 中看到的那样:

    在组合动作时,会推断出正确的组合效果类型

    所以换句话说,由于 Slick 不知道在编译时第一次插入后你要做什么,所以编译失败。而as the documentation says,“无法融合这些动作以提高执行效率”。

    【讨论】:

    • 我能否以某种方式指定两个case 分支的主体返回Unit,因此明确指出两种返回类型都被忽略(但更重要的是,两种类型相同,从而安抚编译器)?
    • 另外,我在您提供的声明的链接中找不到“无法融合此操作以更有效地执行”。我错过了什么吗?
    • 嗯,他们不返回单位,他们返回 DBIOAction(这是你需要从 flatMap 返回的)。但是,您应该能够为编译器提供一些有关类型的帮助以解决此问题,例如通过指定 flatMap 操作中使用的类型,如果我没记错的话,在你的情况下是 flatMap[Int, NoStream, Effect.Write] { id =>
    • @alextsc 这是正确答案。谢谢你。如果您将其写为答案,我将标记为已回答。
    • @alextsc 我长期以来一直将flatMap 视为运算符,而不是我忘记可以附加类型参数的方法!
    猜你喜欢
    • 2021-11-19
    • 2021-03-20
    • 2016-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多