【问题标题】:Haskell to Python: multiple-functions conversion issueHaskell 到 Python:多函数转换问题
【发布时间】:2012-11-01 17:46:26
【问题描述】:

我对编程很陌生,我被要求将 3 个 haskell 函数转换为 python 作为练习。 这 3 个函数是相连的,因为其中一个函数的输出用作下一个函数的输入,以此类推。

我知道 haskell 函数的作用,但我不知道如何开始转换它们!

这是haskell代码:

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)

这是我转换它的尝试:

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()

嗯,首先我相信这不是 haskell 代码的“直接转换”。不过这样也可以,但是第二,它不起作用。

这种缺乏编程背景的情况让我快要死了……谁能帮我解决这个问题?

非常感谢!

编辑:

这个问题的重点是将haskell准确地转换为python。 我自己做了一个精简版,这是练习的下一步^^

【问题讨论】:

  • 将代码从一种您不完全理解的语言转换为另一种您不完全理解的语言是一种学习编程的糟糕方式。我会建议任何给你练习的人,让他们首先让你感觉舒适地用一种语言阅读和编写代码。

标签: python haskell code-conversion


【解决方案1】:

首先,放弃 class 包装器 - 这不是必需的。

直接的 Python 翻译类似于:

# 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)

但是这里的递归风格不是很 Pythonic。下一个练习:将递归替换为迭代、列表推导或对reduce 的调用(如果在 Python2 上)。

【讨论】:

  • 最后的练习,阅读 stdlib 中math 模块中的factorial 函数:D
  • 哦,我很惊讶这竟然如此简单!不知道haskell与python如此相似。非常感谢!
  • 这段代码的问题不在于它不是pythonic(即不是惯用的Python),而是它给初学者一种Python和Haskell相似的错误印象。 Python 的列表是连续数组,因此获取剩余成员对于长列表来说是一项昂贵的操作。换句话说,Python 的ar = arr[1:] 在 CPU 和内存使用方面与 Haskell 对第一个和剩余列表元素的解包有很大不同。
  • 呃,但现在如何让变量从一个函数传递到另一个函数?这是我第一次使用多个函数,这就是我使用类包装器的原因^^'
  • @EdwardCoelho 与在 Haskell 源代码中的方式相同,它们在函数调用中作为参数给出。 :)
【解决方案2】:

如果您想编写惯用的 Python,请避免递归。

down(n) 拼写为range(n, 0, -1)。如果你想要惰性语义,请使用xrange,这将更接近 Haskell 的精神。

product(lst)reduce(operator.mul, lst, 1)。 (直接拼出循环会更惯用,但这样更短。)

从那里开始应该很明显如何转换factorial

【讨论】:

  • 哇,谢谢!我真的应该使用惰性语义并且不知道!
  • 如果你喜欢惰性语义,你会喜欢generators。 Python 比人们想象的要懒惰。 :)
  • @EdwardCoelho 不客气。如果您发现答案有用,请随时单击“接受”按钮。 :)
  • 我当然做到了!我只是想完成代码。我总是在接受之前这样做:p
  • 如果你喜欢惰性语义并且能够多次使用值,你会讨厌生成器。
猜你喜欢
  • 2019-10-14
  • 1970-01-01
  • 2010-12-29
  • 1970-01-01
  • 2017-04-11
  • 1970-01-01
  • 2012-02-12
  • 2013-03-02
  • 1970-01-01
相关资源
最近更新 更多