scala - Scala compiler infers overly specific type with complex type parameter
问题描述
I'm writing an FRM, with the fields abstracted over F[_]
.
trait Query[A]
case class Field[A](name: String)
case class DBTable[T[_[_]]](fields: T[Field]) extends Query[T[Field]]
// example table
case class PersonalInfo[F[_]](name: F[String], age: F[Int])
I want to perform query rewrites using recursion schemes, so I need to define a pattern functor,
trait QueryF[A, B]
case class DBTableF[T[_[_]], B](fields: T[Field]) extends QueryF[T[Field], B]
and then a coalgebra
to lift the Query into it:
type Coalgebra[F[_], A] = A => F[A]
def coalg[A]: Coalgebra[QueryF[A, ?], Query[A]] = {
case DBTable(fields) => DBTableF(fields)
}
This works, but defining an algebra
to convert in the opposite direction does not:
type Algebra[F[_], A] = F[A] => A
def alg[A]: Algebra[QueryF[A, ?], Query[A]] = {
case DBTableF(value) => DBTable[A](value)
}
the alg function throws a compiler error, saying constructor of type controllers.thing.DBTableF[T,B] cannot be uniquely instantiated to expected type controllers.thing.QueryF[?,controllers.thing.Query[?]
解决方案
How about this here:
import scala.language.higherKinds
trait Query[A]
case class Field[A](name: String)
case class DBTable[T[_[_]]](fields: T[Field]) extends Query[T[Field]]
trait QueryF[A, B]
case class DBTableF[T[_[_]], B](fields: T[Field]) extends QueryF[T[Field], B]
type Coalgebra[F[_], A] = A => F[A]
def coalg[A]: Coalgebra[({ type L[X] = QueryF[A, X]})#L, Query[A]] = {
case DBTable(fields) => DBTableF(fields)
}
type Algebra[F[_], A] = F[A] => A
def alg[A]: Algebra[({ type L[X] = QueryF[A, X]})#L, Query[A]] = {
case dbtf: DBTableF[t, b] => DBTable(dbtf.fields)
}
or alternatively, with the last case
replaced by:
case dbtf: DBTableF[t, b] => DBTable[t](dbtf.fields)
if this is a bit clearer.
Both variants compile with -Ypartial-unification
on 2.12.6.
推荐阅读
- model-view-controller - 从 asp.net mvc 核心中的视图调用控制器操作
- html - iOS 13 浏览器问题
- javascript - 为网站中的静音/取消静音设置 cookie
- python - 在同一个 django forms.ModelForm 类中访问 froms.filed 的值
- node.js - 使用 nodejs 请求模块以 POST
- angular - 结合来自两个 Angular 项目(和 dotnet)的代码覆盖率
- css - 如何确保 osx 和 windows 之间的滚动条样式一致性?
- angular - Angular 全球服务
- reactjs - 在按钮单击时增加变量的值
- flutter - Riverpod 结构,用于使用自己的提供程序的项目列表