title: How do I provide the proper type information to get my generic filter function working for slick
body: <p>I'm trying to implement some generic filters in a base class for my slick tables. </p>
  
  <p>What I'm trying to accomplish is the ability to translate url query strings into database filters. I've come up with a working solution, but the code isn't very DRY. </p>
  
  <p>This is my modified code. </p>
  
  <pre><code>package db.utils.repos
  
  import common.utils.request.filters.{StringMatchesFilter, RequestFilter}
  import scala.slick.lifted.{Column =&gt; LiftedColumn}
  import db.environments.slick.interfaces.SlickEnv
  import org.joda.time.DateTime
  
  import scala.slick.profile.RelationalProfile
  
  trait SlickPageable {
  
    val slickEnv: SlickEnv
  
    import slickEnv.profile.simple._
  
    trait FieldMapped {
      def longField(f: String): Option[LiftedColumn[Long]]
  
      def optLongField(f: String): Option[LiftedColumn[Option[Long]]]
  
      def stringField(f: String): Option[LiftedColumn[String]]
  
      def optStringField(f: String): Option[LiftedColumn[Option[String]]]
    }
  
    trait FieldSet{
      def stringField(table: FieldMapped, f: String): Option[LiftedColumn[Any]]
    }
  
    object FSet extends FieldSet {
      override def stringField(table: FieldMapped, f: String): Option[LiftedColumn[String]] = {
        table.stringField(f)
      }
  
    }
  
    object OptFSet extends FieldSet {
      override def stringField(table: FieldMapped, f: String): Option[LiftedColumn[Option[String]]] = {
        table.optStringField(f)
      }
    }
  
    def filter(table: FieldMapped, f: RequestFilter) = {
      queryFilter(table, f, QSet)
    }
  
    def optFilter(table: FieldMapped, f: RequestFilter) ={
      queryFilter(table, f, OptQSet)
    }
  
  
    def queryFilter[T, R](table: FieldMapped, f: RequestFilter, querySet: QuerySet[T, R]) = {
      def checkField[A](field: Option[A], op: (A, String) =&gt; R) = {
        field match {
          case Some(fi) =&gt;
            op(fi, f.value)
          case None =&gt;
            throw new IllegalArgumentException(s"could not retrieve field ${f.field}")
        }
      }
      f match {
        case sf: StringMatchesFilter =&gt; {
              checkField(querySet.fSet.stringField(table, f.field), querySet.sEq)
        }
        case _ =&gt; throw new IllegalArgumentException("No such filter")
      }
    }
  
    trait QuerySet[T, R] {
      val fSet: FieldSet
      def sEq(col: T, value: String): R
    }
  
    object QSet extends QuerySet[LiftedColumn[String], LiftedColumn[Boolean]] {
      override val fSet = FSet
      override def sEq(col: LiftedColumn[String], value: String): LiftedColumn[Boolean] = {
        col === value
      }
    }
  
    object OptQSet extends QuerySet[LiftedColumn[Option[String]], LiftedColumn[Option[Boolean]]] {
      override val fSet = OptFSet
      override def sEq(col: LiftedColumn[Option[String]], value: String): LiftedColumn[Option[Boolean]] = {
        col === value
      }
    }
  
  }
  </code></pre>
  
  <p>And the error message </p>
  
  <pre><code>type mismatch;
  [error]  found   : (T, String) =&gt; R
  [error]  required: (scala.slick.lifted.Column[_], String) =&gt; R
  [error]             checkField(fieldSet.stringField(table, f.field), querySet.sEq)
  </code></pre>
  
  <p>If I remove the <code>FieldSet</code> from the <code>queryFilter</code> parameter list I can get it working. But then I need to separate functions: one to call the field mapping methods, and the other to call the optional field mapping methods. It works though, with the type inferencing and everything working properly. </p>
  
  <p>So how can I get this working with <code>FieldSet</code>? From what I can tell it seems there isn't enough type information at compile time. But I don't know how to provide it.</p>