Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/svg/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在haskell中实现[x if func(x,lst)for x in list]?_Haskell_Recursion - Fatal编程技术网

如何在haskell中实现[x if func(x,lst)for x in list]?

如何在haskell中实现[x if func(x,lst)for x in list]?,haskell,recursion,Haskell,Recursion,好的,我来自python背景,是haskell的新手,正在做作业。问题本身我已经解决了,但我的逻辑/代码看起来很难看,我想知道如何改进它。我想做的是用这个列表作为参数来迭代一个列表,以调用另一个函数 checksOnce :: [Int] -> [Int] checksOnce xs = go xs xs where go [] _ = [] go (x:xs) lst | occursOnce x lst = x : go xs lst

好的,我来自python背景,是haskell的新手,正在做作业。问题本身我已经解决了,但我的逻辑/代码看起来很难看,我想知道如何改进它。我想做的是用这个列表作为参数来迭代一个列表,以调用另一个函数

checksOnce :: [Int] ->  [Int]
checksOnce xs = go xs xs
  where go [] _ = []
        go (x:xs) lst
          | occursOnce x lst = x : go xs lst
          | otherwise = go xs lst
假设我想在haskell中实现以下目标

input = [1,2,2,3,3,4,5]
output = [1,4,5] #occurs Once
所以我想从x->y开始

通常我会怎么做

def checksOnce(input):
  lst = []
  for val in input:
    if occursOnce(val,input):
      lst.append(val)
  print(lst)
如何在haskell中进行迭代?我有一个函数可以很好地处理ocursOnce,它接受一个值和一个列表并返回一个bool,就像python一样

checksOnce :: [Int] -> [Int] -> [Int]
checksOnce [] lst = []
checksOnce (x:xs) lst
  | occursOnce x lst = [x] ++ checksOnce xs lst
  | otherwise = checksOnce xs lst
和mainFunc lst=checksOnce lst lst之类的函数来调用上述函数

checksOnce :: [Int] ->  [Int]
checksOnce xs = go xs xs
  where go [] _ = []
        go (x:xs) lst
          | occursOnce x lst = x : go xs lst
          | otherwise = go xs lst
以上方法很好,就我的硬件而言已经足够了,但是一次通过相同的参数是多余的!如何从checksOnce:[Int]->[Int]->[Int]转到checksOnce:[Int]->[Int],并像上面的python代码一样只使用一个列表进行迭代,而不是将相同的列表一次性传递给函数


谢谢

在Haskell中编写此函数最简单、可能也是最惯用的方法是使用过滤器:

或者,如果您更愿意,尽管增益有争议,以无点风格重写lambda:

checksTwice :: (Eq a) => [a] -> [a]
checksTwice xs = filter (flip occursTwice xs) xs

这正是@user2407038评论中建议的答案-为窃取您的答案道歉哈斯克尔有列表理解,因此您可以:

\f xs -> [x | x <- xs, f x xs]

就像在Python中一样,您希望变量lst只对函数checksTwice可见,而不是参数。Haskell因为缺少循环原语而让一些人陷入循环——解决方案通常是高阶函数的辅助函数

checksOnce :: [Int] ->  [Int]
checksOnce xs = go xs xs
  where go [] _ = []
        go (x:xs) lst
          | occursOnce x lst = x : go xs lst
          | otherwise = go xs lst
但是这个模式,包括x当且仅当fx只是一个过滤器,所以

checksOnce x = filter (`occursOnce` lst) xs

正如@RobinZigmond所指出的,与您所希望的行为相比,这仍然存在一个bug。

您的python代码和haskell代码不是都将结果中的每个条目放了两次吗?例如,输出[2,2,3,3]而不是[2,3]。如果只检查x是否在xs中出现一次以避免重复,不是更好吗?请在您的问题中添加您的OccursTworth函数Python和Haskell版本。我相信您的Haskell版本应该在最后两行的等号右侧都有checksTwice,将同一个参数重复两次是多余的,因为checksTwice的第一个参数会更改,而第二个参数不会更改。这两个论点有不同的目的,你用它们做不同的事情;碰巧它们在顶级调用中具有相同的值。另一种写入checksTwice的方法是\lst->filter flip发生两次lst-lst。为什么您不得不使Haskell代码与Python代码相似,即表面上相似?@SyedShariqAli问题的核心是将此函数调用视为额外调用。Haskell没有迭代,只有递归。此外,具有起始条件的递归函数通过向其传递初始值的辅助函数来实现。请注意,在Haskell和Python中,这个函数都可以通过代码实现,在代码中,输入在语法上正好出现两次。您给出了两种语言的代码,这两种语言都可以实现。您能解释一下代码吗?这看起来很酷。我来核对一下清单。谢谢你有什么特别的事要我说吗?它们都是匿名函数lambdas,接受两个变量:谓词,您称之为f;还有这个列表,我在哈斯凯尔传统中称之为xs。@SadisticSardines[x | x