2017-09-29 85 views
0

所以我有一个通用的组合器。Scala泛型与递归

回想一下,两个函数-F的组成和g--是h(x)= F(G(X))

def inc(x: Double) = x + 1 
    def double(x: Double) = 2 * x 

    def compose[A,B,C](f: B => C, g: A => B, x: A): C = f(g(x)) 

    //TEST 
    println(compose(double, inc, 2.0)) 
    //OUTPUT 
    // 6.0 

但现在我想要实现的自组合物迭代组合子, 递归,用我的构建功能,其中:

def selfIter[T](f: T=>T, n: Int) = f composed with itself n times. 

我试着这样做:

def selfIter[T](f: T, n: Int): T = { 
     if(n == 0) f 
     else f + selfIter(f, n-1) 
    } 

    //TEST 
    println(selfIter(compose(double, inc, 2.0), 2)) 

我得到一个错误,我知道我正在做一些根本性错误,但我无法弄清楚我需要做什么。

在这种情况下,输出应该是14.0因为第一呼叫将是2(2 + 1)= 6.0,然后第二呼叫将是2(6.0 + 1)= 14.0

问题:我应该如何修改我的代码,以便selfIter将组成f控制自己n次,直到我们有N == 0,并返回最终值

回答

3

解决这类问题的最简单方法是使用组合子由Scala提供。你也应该首先编写要使用,然后在功能应用输入

def compose[A,B,C](f: B => C, g: A => B): A => C = g.andThen(f) 
def selfIter[T](f: T=>T, n: Int): T => T = Function.chain(List.fill(n)(f)) 
println(selfIter(compose(double, inc), 2)(2.0)) 

如果撰写签名不能再改

def compose[A,B,C](f: B => C, g: A => B, x: A): C = f(g(x)) 
def selfIter[T](f: T=>T, n: Int): T => T = Function.chain(List.fill(n)(f)) 
println(selfIter[Double](compose(double, inc, _), 2)(2.0)) 

但它使更多的意义上的第一个解决方案

+0

如果我不允许在撰写功能中更改任何内容,该怎么办?我会如何做到这一点?递归是必须的 – Phillip

+0

可以解释一些关于撰写第三个参数。为什么你使用了_以及如何使用这个函数.chain和list.fill – Phillip

+1

如果你看'selfIter'方法,第一个参数是类型T => T,我们可以通过传递'(v:Double)= > compose(double,inc,v)',这相当于'compose(double,inc,_)' – Mikel

2

这里有一些事情出错了。

f + selfIter(f, n-1)f(类型T)必须有一个+方法,该方法另一T作为参数。但是你不想添加这些东西,你想编写它们。

这里有一个更简单的方法来获得你的结果。

Stream.iterate(2.0)(compose(double, inc, _))(2) // res0: Double = 14.0 

如果您打算使用递归方法,这似乎实现了您的目标。

def selfIter[T](start:T, n:Int)(f:T=>T): T = { 
    if (n < 2) f(start) 
    else f(selfIter(start, n-1)(f)) 
} 
selfIter(2.0, 2)(compose(double, inc, _)) // res0: Double = 14.0 
+0

这也适用!谢谢 – Phillip