【问题标题】:Haskell equivalent of this Python code这个 Python 代码的 Haskell 等价物
【发布时间】:2014-04-26 01:11:40
【问题描述】:

我在 Python 之后学习 Haskell,我认为创建一个函数来查找一个序列中不在另一个序列中的所有项目(其中两个序列都有可以比较的元素)将是一个有趣的练习。我很容易在 Python 中为此编写了一些代码:

def inverse(seq, domain):
    ss = iter(seq)
    dd = iter(domain)
    while True:
        s = next(ss)
        while True:
            d = next(dd)
            if d != s:
                yield d
            if d >= s:
                break

seqdomain 均已排序)

但是,我很难将这段代码转换为 Haskell。我想我只会使用列表(可能是无限的)而不是ssdd,我想我会使用s = next(ss)s = head ssss = tail ss 相同,但我可以'不知道如何将其翻译成 Haskell。我也无法弄清楚如何处理两个 while 循环。我想我可以使用无限递归,但由于有两个循环,我不知道是否需要两个函数或什么。

【问题讨论】:

  • filter (not . (`elem` domain)) seq。或者用简单的英语:filter out all that is not element of domain
  • 我不太确定您的 python 代码是否符合您的想法。这不仅仅是两个列表的区别。顺便说一句,您可以在 Haskell 中使用 Data.List.(\\) 进行计算
  • 您可以使用pipes 获得类似协程的行为。您可以使用Foldable.toList 获得类似iter 的行为。

标签: python haskell code-translation


【解决方案1】:

我不能完全让您的代码像宣传的那样工作,但我认为这个 sn-p 应该与您的工作方式大致相同,但有两个假设:X 和 Y 已排序,并且所有元素都是唯一的。

我们想从xx 中删除yy 中的所有元素。在每一步,我们只需要比较它们的第一个元素(xy,在函数定义中)。然后可能会发生三件事:

  • x小于y,表示x不在yy中,所以我们可以接受x
  • x 等于 y,我们拒绝 x
  • x大于y,这意味着我们需要在yy中前进,然后才能确定是拒绝还是接受x

这是函数定义:

minus :: Ord a => [a] -> [a] -> [a]  
minus xx@(x:xs) yy@(y:ys) = case (compare x y) of  
  LT -> x : minus xs yy  
  EQ ->     minus xs ys  
  GT ->     minus xx ys  
minus xs _  = xs  

【讨论】:

  • Python 中的生成器转换为 Haskell 中的“受保护”或“高效”递归。这就是我们有类似SomeConstructor foo bar (recursion goes here) 的地方。如果该递归永远循环,我们仍然可以在SomeConstructor 上进行模式匹配,只要我们不强制评估它的第三个字段。在上面的示例中,这是使用x : ... 完成的。无论出于何种原因,如果您对这背后的理论感兴趣,那么 coduction、codata 和 corecursion 就是相关的概念。
  • 我想你的意思是LT -> x : minus xs yy
  • GT 的情况看起来很奇怪:在 Python 代码中,当 d > s 产生 d 并中断时,我认为我们会前进到 xsys?也许GT -> x : minus xs ys 的表现也一样?
  • @chi:我认为这是 python 中的一个错误,因为它使inverse([1,2,3,4],[2,3,4]) 产生 2、3、4
  • @rampion 啊,我明白了。我没有看 Python 程序要做什么,只看它做了什么。 :)
猜你喜欢
  • 1970-01-01
  • 2019-02-12
  • 2011-01-28
  • 1970-01-01
  • 1970-01-01
  • 2018-11-30
  • 2017-10-17
  • 2021-12-26
  • 1970-01-01
相关资源
最近更新 更多