0
\$\begingroup\$

As an exercise, I wanted to rewrite this toy Python code in Haskell:

def f(x):
    return abs(42-x)**2

def improve(x):
    newX = x + 0.1
    return newX, f(newX)

def optimize(f, goal):
    x = 0
    err = f(x)
    while not err < goal:
        x, err = improve(x)
    return x, err

print(optimize(f, 0.5))

Ideone

My solution works but is quite ugly:

f :: (Num a) => a -> a
f x = abs(42-x)^2

improve :: (Fractional a) => (a -> b) -> a -> (a, b)
improve f x =
    let newX = x+0.1
    in (newX, f newX)

step :: (Fractional a, Ord b) => (a -> b) -> b -> a -> (a, b)
step f goal x =
    let
        newX = x+0.1
        err = f newX
    in
        if err < goal then (newX, err) else step f goal newX

optimize :: (Fractional a, Ord b) => (a -> b) -> b -> (a, b)
optimize f goal = step f goal 0

main :: IO ()
main = print $ optimize f 0.5

Ideone

I am trying to find a solution without explicit recursion using a fold or something, but did not have an idea yet on how to do it. Can anybody help me out?

\$\endgroup\$
1
\$\begingroup\$

The guys at #haskell pointed me to until. This makes it satisfactory to me.

f :: Num a => a -> a
f x = abs(42-x)^2

improve :: Fractional b => (b -> c) -> (b, a) -> (b, c)
improve f (x, _) = (newX, f newX) where newX = x+0.1

optimize:: (Ord a, Fractional b) => (b -> a) -> a -> b -> (b, a)
optimize f goal x = until isDone (improve f) (0, f x)
    where isDone (_, err) = err < goal

main :: IO ()
main = print $ optimize f 0.5 0

http://ideone.com/ZlC7x8

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.