问题
I was running the below Scala code in Worksheet:
package src.com.sudipta.week2.coursera
import scala.math.abs
import scala.annotation.tailrec
object FixedPoint {
println("Welcome to the Scala worksheet") //> Welcome to the Scala worksheet
val tolerance = 0.0001 //> tolerance : Double = 1.0E-4
def isCloseEnough(x: Double, y: Double): Boolean = {
abs((x - y) / x) / x < tolerance
} //> isCloseEnough: (x: Double, y: Double)Boolean
def fixedPoint(f: Double => Double)(firstGuess: Double): Double = {
@tailrec
def iterate(guess: Double): Double = {
val next = f(guess)
if (isCloseEnough(guess, next)) next
else iterate(next)
}
iterate(firstGuess)
} //> fixedPoint: (f: Double => Double)(firstGuess: Double)Double
def myFixedPoint = fixedPoint(x => 1 + x / 2)(1)//> myFixedPoint: => Double
myFixedPoint //> res0: Double = 1.999755859375
def squareRoot(x: Double) = fixedPoint(y => (y + x / y) / 2)(1)
//> squareRoot: (x: Double)Double
squareRoot(2) //> res1: Double = 1.4142135623746899
def calculateAverate(f: Double => Double)(x: Double) = (x + f(x)) / 2
//> calculateAverate: (f: Double => Double)(x: Double)Double
def myNewSquareRoot(x: Double): Double = fixedPoint(calculateAverate(y => x / y))(1)
//> myNewSquareRoot: (x: Double)Double
myNewSquareRoot(2) //> res2: Double = 1.4142135623746899
}
What is making me confused are:
- Scala worksheet is showing below for my fixedPoint function
fixedPoint: (f: Double => Double)(firstGuess: Double)Double
What is this? Is this function type/ function definition or I am missing the term? Basically how I can explain this function in English?
- Scala worksheet is showing below for my calculateAverate function
calculateAverate: (f: Double => Double)(x: Double)Double
But it looks to me the return type of my function is Double, but I was expecting Double => Double. The reason is I am going to use this with fixedPoint which expects Double => Double like below:
def myNewSquareRoot(x: Double): Double = fixedPoint(calculateAverate(y => x / y))(1)
Please help me to understand Higher Order Function / Currying more clearly. Thanks in advance.
回答1:
The function
def fixedPoint (f: Double => Double)(firstGuess: Double):Double
is a function definition which takes two arguments:
- a function "f" which takes a parameter of type
Double
which returns aDouble
and - a
Double
value named "firstGuess"
and returns a Double
. The separation of the single parameters into their own parenthesis groups allows the function to be used in currying:
def mySqrtCalc(x:Double)(firstGuess:Double):Double = {...}
val mySqrtFunc = mySqrtCalc(2.0) _
val v = mySqrtFunc(1) // parameter firstGuess is set to 1
Beside the ability for currying, this is equivalent to the uncurried version
def fixedPoint (f: Double => Double,firstGuess: Double):Double
which might look more familiar to you.
The result of the calculateAverate
is a Double because you add up the result of applying the passed function f to x with x which gives you a Double
because f is a function Double => Double
.
You use calculateAverate
method in a curried way in your myNewSquareRoot
method body, by giving only the first of both parameters in first place and omitting the second one, which is taken from the from the outer fixedPoint
method. Omitting the second parameter of calculateAverate
gives you a method Double=>Double
as it is required by the fixedPoint
method.
You might insert some println(s"<methodname> value=$value")
to observe the execution flow and understand the method call order.
回答2:
fixedPoint: (f: Double => Double)(firstGuess: Double)Double
The task here is to find fixed points of functions and the application of the task will be to our well known square root with Newton's method
Square Root by Newton's method:
Calculates the square root of parameter x
def sqrt(x: Double): Double = ...
The classical way to achieve this is by successive approximations using Newton’s method.
To compute sqrt(x):
- Start with an initial estimate y (let’s pick y = 1).
- Repeatedly improve the estimate by taking the mean of y and x/y.
Example: x=2
Estimation Quotient Mean
1 2/1=2 1.5
1.5 2/1.5=1.333 1.4167
1.4167 2/1.4167=1.4118 1.4142
1.4142 so on
First, define a function which computes one iteration step
def sqrtIter(guess: Double, x: Double): Double =
if (isGoodEnough(guess, x)) guess
else sqrtIter(improve(guess, x), x)
Second, define a function improve to improve an estimate and a test to check for terminatation:
def improve(guess: Double, x: Double) =
(guess + x / guess) / 2
def isGoodEnough(guess: Double, x: Double) =
abs(guess * guess - x) < 0.001
Third, define the sqrt function:
def sqrt(x: Double) = srqtIter(1.0, x)
using your Fixedpoint function we also calculating square root of a number
first see what is fixed point:
A number x
is called a fixed point of a function f if f(x) = x
For some functions f we can locate the fixed points by starting with an initial estimate and then by applying f in a repetitive way.
x, f(x), f(f(x))
This leads to the following function for finding a fixed point:
val tolerance = 0.0001
def isCloseEnough(x: Double, y: Double) =
abs((x - y) / x) / x < tolerance
def fixedPoint(f: Double => Double)(firstGuess: Double) = {
def iterate(guess: Double): Double = {
val next = f(guess)
if (isCloseEnough(guess, next)) next
else iterate(next)
}
iterate(firstGuess)
}
In this formulation,fixedPoint
is a function which returns another function, namely the specialized function iterate
here fixedPoint
def fixedPoint(f: Double => Double)(firstGuess: Double)
the function fixedPoint
is applied to the function f: Double => Double
. The resulting
function is then applied to the second argument
(firstGuess: Double)
This notation is possible because function application associates to the left. That is,
if args1 and args2 are argument lists, then f(args1)(args2)
is equivalent to (f(args1))args2
In your program first argument is function that take input type is Double and return type is Double and then apply this function to the guess
reformulation of the square root function.
Let’s start with a specification of sqrt:
sqrt(x) = the y such that y*y = x
= the y such that y = x / y
Hence, sqrt(x) is a fixed point of the function y => x / y
. This suggests that
sqrt(x)
can be computed by fixed point iteration:
def sqrt(x: double) = fixedPoint(y => x / y)(1.0)
this is a long answer but i think it will help you to understand the concept
来源:https://stackoverflow.com/questions/19806760/scala-higher-order-function-little-confused