Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type mismatch during refactoring using Slick

Tags:

scala

slick

I have the following piece of code I'd like to make 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, /* ... */)
    }
  }

That compiles fine. But if I consolidate the two into the following:

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, /* ... */)
      }
    }
  }

I get the following type mismatch error:

[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

I can't seem to figure out why. Can someone illuminate this for me?

like image 709
Dan Li Avatar asked Mar 12 '23 13:03

Dan Li


2 Answers

The compiler can't figure out the used effect type correctly. As a workaround you should be able to give it some help by specifiying types used, e.g. in the flatMap operation, which would be

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

in your case.

like image 100
alextsc Avatar answered Mar 23 '23 12:03

alextsc


I am afraid you can't refactor the code that way. I know that from the point of view of the code it looks reasonable. But the pattern matching in the flatMap doesn't give enough information to the compiler to infer the effect to the DBIOAction.

As you can read in the source code:

When composing actions, the correct combined effect type will be inferred

So in other words, as Slick doesn't know what are you going to do after the first insertion in compilation time, the compilation fails. And as the documentation says, "it is not possible to fuse this actions for more efficient execution".

like image 33
Carlos Vilchez Avatar answered Mar 23 '23 10:03

Carlos Vilchez