感谢 Mark Harrah 完成了这个解决方案。诀窍是Function1
标准库中没有以足够通用的方式定义。
我在问题中的“闭包”特征实际上是函子之间的自然转换。这是“函数”概念的概括。
trait ~>[F[_],G[_]] { def apply[B](f: F[B]): G[B] }
一个功能a -> b
那么应该是这个特性的特化,是 Scala 类型类别上两个内函子之间的自然转换。
trait Const[A] { type Apply[B] = A }
type ->:[A,B] = Const[A]#Apply ~>: Const[B]#Apply
Const[A]
是一个函子,将每种类型映射到A
.
这是我们的列表类型:
type CList[A] = ({type f[x] = Fold[A,x]})#f ~> Endo
Here, Endo
只是将类型映射到其自身的函数类型的别名(内功能 http://en.wikipedia.org/wiki/Endofunction).
type Endo[A] = A ->: A
And Fold
是可以折叠列表的函数类型:
type Fold[A,B] = A ->: Endo[B]
最后,这是我们的列表构造函数:
def cons[A](x: A) = {
new (CList[A] ->: CList[A]) {
def apply[C](xs: CList[A]) = new CList[A] {
def apply[B](f: Fold[A,B]) = (b: B) => f(x)(xs(f)(b))
}
}
}
def nil[A] = new CList[A] {
def apply[B](f: Fold[A,B]) = (b: B) => b
}
需要注意的是,需要将 (A ->: B) 显式转换为 (A => B) 以帮助 Scala 的类型系统顺利进行。因此,在创建后实际折叠列表仍然非常冗长和乏味。这是用于比较的等效 Haskell:
nil p z = z
cons x xs p z = p x (xs p z)
Haskell 版本中的列表构造和折叠非常简洁且无噪音:
let xs = cons 1 (cons 2 (cons 3 nil)) in xs (+) 0