2017-09-29 84 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