Scala 后面定义的多类型参数

Scala Multiple type parameter that are defined later

我正在尝试将 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))

所以,我想到的解决方案是将 crush 函数拆分为更多部分,这样我就可以为 crush 函数使用相同的 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))
    }
}

所以,我的问题是:有没有更好的方法来解决这个问题?

实际上,您的第一个解决方案唯一的错误是您遗漏了 repfrep 之间的点。我还建议您不要显式使用 return,也不要隐藏类型参数的名称 (A):

def crush[B,A,F[_]](asc : Assoc)(f : A => B => B)(z : B)(x : F[A])(implicit rep : FRep[({type AB[X] = Crush[B,X]})#AB,F]): B = {
    def fCrush = new Crush[B,A]{ 
      override def selCrush: Assoc => A => B => B = _ => f
    }
    rep.frep(fCrush).selCrush(asc)(x)(z)
}

现在您可能会问自己:如果所有错误都是缺少点,为什么会显示此错误消息?好吧,scala 支持中缀表示法。它将 a b c d e 解析为 a.b(c).d(e)。但是你写了这样的东西:a b(c).d(e)。这会使解析器感到困惑。您可以看到当您将 //print 附加到 REPL(我认为是 2.11.8 或更高版本)中的代码并按 TAB 键时会发生什么。

我为你过滤掉了所有的垃圾。 rep frep(fCrush).selCrush(asc)(x)(z) 被解析为:

rep.frep[A](fCrush.selCrush(asc)(x)(z))

在该表达式中 x 确实需要是类型 A 而不是 F[A]

老实说:对我来说,这有点像 scalac 设法解析你的无点代码的错误,完全忽略了过程中的括号。 让我们称之为不幸的语法怪癖:-)