【发布时间】:2017-01-11 20:31:55
【问题描述】:
我正在尝试将 Haskell 的通用库移植到 Scala。但是,我目前对如何解决 Scala 中的通用 Crush 函数并不满意。
我定义了以下处理 Crush 功能的方法。
trait FRep[G[_],F[_]]{
def frep[A](g1 : G[A]) : G[F[A]]
}
trait Crush[B,A]{
def selCrush : Assoc => A => B => B
}
接下来,我想定义crush函数,但在这里我遇到了问题。问题是我需要这个 FRep 特征来表示 Crush 函数,但是 frep 中的 G(Generic) 只允许 1 个参数。我使用 lambda 类型解决了这个问题,但在定义函数时仍然存在一些问题。这是我想要工作的方法:
def crush[B,A,F[_]](asc : Assoc)(f : A => B => B)(z : B)(x : F[A])(implicit rep : FRep[({type AB[A] = Crush[B,A]})#AB,F]): B = {
def fCrush = new Crush[B,A]{
override def selCrush= _ => f
}
return(rep frep(fCrush).selCrush(asc)(x)(z))
}
这显然报错了,因为crush函数中的A参数与隐式rep变量中的A lambda类型不一样,需要相同才能使用Crush函数。这是我收到的错误:
<pastie>:677: error: type mismatch;
found : x.type (with underlying type F[A])
required: A
return(rep frep(fCrush).selCrush(asc)(x)(z))
所以,我想出的解决方案是将粉碎函数拆分为更多部分,这样我就可以将相同的 A 用于粉碎函数。这是当前编译的解决方案:
class CrushFunction[B,F[_]](asc : Assoc)(z : B)(implicit rep : FRep[({type AB[A] = Crush[B,A]})#AB,F]){
def crush[A](f : A => B => B)(x : F[A]) : B = {
val crushVal = new Crush[B,A]{
override def selCrush: Assoc => A => B => B = _ => f
}
return(rep.frep(crushVal).selCrush(asc)(x)(z))
}
}
所以,我的问题是:有没有更好的方法来解决这个问题?
【问题讨论】:
标签: scala generics type-conversion generic-programming