2017-07-20 23 views
1

我正在Scala中实现List类型,当遵循一本书时。Scala将通用函数传递到另一个泛型函数混淆

这里是我的列表类型的定义:

sealed trait List[+A] 

case object Nil extends List[Nothing] 
case class Cons[+A](head: A, tail: List[A]) extends List[A] 

所有后述的功能在同伴对象列表定义在同一个文件

object List 

我写foldLeftfoldRight为以下

def foldLeft[A,B](l: List[A], z: B)(f: (B, A) => B): B = l match { 
    case Nil => z 
    case Cons(x, xs) => foldLeft(xs, f(z, x))(f) 
} 

def foldRight[A,B](l: List[A], z: B)(f: (A, B) => B): B = l match { 
    case Nil => z 
    case Cons(x, xs) => f(x, foldRight(xs, z)(f)) 
} 

有一个exerci这本书是用foldRight实施foldLeft。这是我的初步实施

def foldLeftWithRight[A,B](l: List[A], z: B)(f: (B, A) => B): B = { 
    foldRight(l, z)((a: A, b: B) => f(b, a)) 
} 

然后我觉得我应该写另一个函数做相反的论点,如果我使用foldLeft实现foldRight。如下:

def reverseArgs[A,B](f: (A, B) => B): (B, A) => B = { 
    (b: B, a: A) => f(a, b) 
} 

因此,我改变的foldLeftWithRight代码为以下:

def foldLeftWithRight[A,B](l: List[A], z: B)(f: (B, A) => B): B = { 
    foldRight(l, z)(reverseArgs(f)) 
} 

和IntelliJ抱怨reverseArgs(f)

类型不匹配:预期(A,B)= > B,actual(B,B)=> B

当我尝试编译代码,错误是:

Error:(21, 37) type mismatch; 
    found : (B, A) => B 
    required: (B, Any) => Any 
     foldRight(l, z)(reverseArgs(f)) 

一个有趣的现象是,当我使用foldRightWithLeftreverseArgs,有没有问题:

def foldRightWithLeft[A,B](l: List[A], z: B)(f: (A, B) => B): B = { 
    foldLeft(l, z)(reverseArgs(f)) 
} 

这到底是怎么回事?

回答

2

如果重命名reverseArgs功能XY的类型参数,你会得到这样的

def reverseArgs[X ,Y](f: (X, Y) => Y): (Y, X) => Y = ??? 

f键入foldLeftWithRight(B, A) => B。顺便指出,以reverseArgs意味着:

X = B 
Y = A 
Y = B 

我猜的IntelliJ从这里A = B推断,这就是为什么它抱怨(B, B) => B(A, B) => B。 Scalac决定Y = Any,因为它是两个可能无关的类型的最小上界。


好的解决办法是推广更多。返回类型的反转函数不一定是参数类型之一,因此您可以为此引入另一个通用类型:

def reverseArgs[X ,Y, Z](f: (X, Y) => Z): (Y, X) => Z = { 
    (b: Y, a: X) => f(a, b) 
} 
+0

现在,这是有道理的,谢谢! – KenKenKen

相关问题