4

I am pretty new to programming and I was asked to convert 3 haskell functions into python as a practice exercise. The 3 functions are connected, since output of one is used as the input of the next one and so on.

I get what the haskell functions do, but I have no idea how to start converting them!

This is the haskell code:

factorial :: Int -> Int
factorial n = product (down n)

product :: [Int] -> Int
product [] = 1
product (a:as) = a * product as

down :: Int -> [Int]
down 0 = []
down n = n : down (n-1)

And this was my try of converting it:

class function:
    def down(self):
        if self.n == 0:
            self.lista = []
        else:
            self.lista = range(self.n, 0, -1)

    def product(self):
        for x in self.lista:
            if x == []:
                self.product = 1
            if x != []:
                for i in self.lista:
                    self.product = i * self.product

    def factorial(self):
        self.n = int(raw_input("n="))

        self.fact = self.product(self.down(self.n))

        print self.fact
        raw_input()

c = function()
c.factorial()

Well, first I believe this isn't a 'direct conversion' of the haskell code. That would be okay though, but second, it doesn't work.

This lack of programming background is killing me...can anyone help me with this problem?

Thanks a lot!

Edit:

The point of this issue is to exactly convert the haskell into python. I did a stripped version of it myself, it was the next step in the exercise ^^

1
  • Converting code from one language you don't fully understand to another language you don't fully understand is a terrible way to learn programming. I would suggest to whoever is giving you exercises that they get you to the point of feeling comfortable reading and writing code in one language first. Commented Nov 2, 2012 at 2:51

2 Answers 2

7

First off, ditch the class wrapper - that's not needed.

A straight Python translation would be something like:

# factorial :: Int -> Int
def factorial(n):
    return product(down(n))

# product :: [Int] -> Int
def product(arr):
    if len(arr) == 0: return 1
    a, ar = arr[0], arr[1:]
    return a * product(ar)

# down :: Int -> [Int]
def down(n):
    if n == 0: return []
    return [n] + down(n - 1)

But the recursive style is not very Pythonic here. Next exercise: replace recursion with iteration, list comprehensions, or calls to reduce (if on Python2).

Sign up to request clarification or add additional context in comments.

6 Comments

final exercise, read about the factorial function in the math module in the stdlib :D
Oh, I am amazed at how simply this could be! Had no idea haskell was so similar to python. Thanks a lot!
The problem with this code is not that it's unpythonic (i.e. not idiomatic Python), but that it gives the beginner a false impression of similarity between Python and Haskell. Python's lists are contiguous arrays, so getting the remaining members is an expensive operation for long lists. In other words, Python's ar = arr[1:] is quite different in terms of CPU and memory usage from Haskell's unpacking of first and remaining list elements.
Ugh, but now how do I make the variables pass from one function to another? This is my first time working with multiple functions, that's why I used the class wrapper ^^'
@EdwardCoelho Same way as they do in the Haskell source, they are given as parameters in the function calls. :)
|
4

If you want to write idiomatic Python, avoid recursion.

down(n) is spelled as range(n, 0, -1). Use xrange if you want lazy semantics, which would be closer to the spirit of Haskell.

product(lst) is reduce(operator.mul, lst, 1). (It would be more idiomatic to just spell out the loop, but this is shorter.)

From there on it should be obvious how to convert factorial.

7 Comments

Wow thanks! I really should be using lazy semantics and didn't know about that!
If you like lazy semantics, you'll love generators. Python is lazier than people tend to think. :)
@EdwardCoelho You're welcome. If you found the answer useful, feel free to click the "accept" button. :)
I certainly did! I'm just trying to finishing the code. I always do that before accepting :p
If you like lazy semantics and to be able to use values more than once, you'll hate generators.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.