使用Scalaz Functor进行7-arity功能的编译错误

时间:2014-02-06 09:34:18

标签: scala scalaz

我尝试实现this answer并遇到编译错误:

def $match(o: DBObject) = MongoDBObject("$match" -> o)

def getObj(instance   : String,                   contextValue: Option[SpaceId]           = None,
            eventType  : Option[String]    = None,
           sourceValue: Option[Long]      = None, targetValues: Option[Iterable[Long]] = None,
           startDate  : Option[LocalDate] = None, endDate     : Option[LocalDate]      = None) : DBObject = {

…  
}

def getMatchObj = (getObj _).map($match)

错误是:

[info] Compiling 1 Scala source to /mnt/data/backup/dev/projects/bluekarma/bluekarma-  analytics-scala-play2/target/scala-2.10/classes...
[error] /mnt/data/backup/dev/projects/bluekarma/bluekarma-analytics-scala-play2/app/models/Dao.scala:121: Unable to unapply type `(String, Option[modelsIds.SpaceId],   Option[String], Option[Long], Option[Iterable[Long]], Option[org.joda.time.LocalDate], Option[org.joda.time.LocalDate]) => com.mongodb.casbah.query.Imports.DBObject` into a type constructor of kind `M[_]` that is classified by the type class `scalaz.Functor`
[error] 1) Check that the type class is defined by compiling `implicitly[scalaz.Functor[<type constructor>]]`.
[error] 2) Review the implicits in object Unapply, which only cover common type 'shapes'
[error] (implicit not found: scalaz.Unapply[scalaz.Functor, (String, Option[modelsIds.SpaceId], Option[String], Option[Long], Option[Iterable[Long]], Option[org.joda.time.LocalDate], Option[org.joda.time.LocalDate]) => com.mongodb.casbah.query.Imports.DBObject])
[error]   def getMatchObj = (getObj _).map($match)
[error]                      ^
[error] one error found
[error] (compile:compile) Compilation failed
[error] Total time: 3 s, completed Feb 6, 2014 9:53:13 AM

1 个答案:

答案 0 :(得分:3)

我猜这是scala编译器的一个问题:它不能将Function7[...., T]用作M[T]

你可以用这种方式编译:

type MF7[T] = (String, Option[SpaceId], Option[String], Option[Long], Option[Iterable[Long]], Option[LocalDate],  Option[LocalDate]) => T

(getObj _: MF7[DBObject]).map(myMatch)

请注意,您应避免使用名称中的$$在scala中广泛用于生成名称。

map适用于Function6,因此您可以减少参数cont。例如,您可以使用case class

对参数进行分组
case class Period(startDate: Option[LocalDate] = None, endDate: Option[LocalDate] = None)

def getObj(instance: String, contextValue: Option[SpaceId] = None,
           eventType: Option[String] = None, sourceValue: Option[Long] = None,
           targetValues: Option[Iterable[Long]] = None,
           period: Option[Period] = None) : DBObject = ???

val getMatchObj = (getObj _).map(myMatch)

不成形

使用shapeless,您可以将任何arity的函数转换为单HList个参数的函数,反之亦然:

val getMatchObj = (getObj _).toProduct.andThen(myMatch).fromProduct

默认参数

scala函数不能有默认参数,因此保留默认参数的唯一方法是将所有参数提取到case class,如下所示:

case class GetObjArgs(instance: String, contextValue: Option[SpaceId] = None,
               eventType: Option[String] = None, sourceValue: Option[Long] = None,
               targetValues: Option[Iterable[Long]] = None,
               startDate: Option[LocalDate] = None, endDate: Option[LocalDate] = None)

def getObj(a: GetObjArgs): DBObject = ???

val getMatchObj = (getObj _) andThen myMatch

getMatchObj(GetObjArgs("inst", sourceValue = Some(1)))