繁体   English   中英

如何在Haskell中实现[如果列表中的x为func(x,lst),则为x]?

[英]How do i achieve [x if func(x,lst) for x in list] in haskell?

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

假设我想在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中进行迭代? 我有一个功能可以很好地发生的事件,它需要一个值并列出并返回布尔值,就像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] -> [Int]转到checksOnce :: [Int] -> [Int]并像上面的python代码一样仅使用一个列表进行迭代,而不是传递相同列表一次功能?

谢谢

Haskell具有列表理解功能,因此您可以执行以下操作:

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

您也可以使用过滤器执行此操作:

\f xs -> filter (\x -> f x xs) xs

在Haskell中编写此函数的最简单,可能也是最惯用的方法是使用filter

checksTwice :: (Eq a) => [a] -> [a] -- you can keep it as [Int] -> [Int] if you like, but this more general type signature is better because the function works on any type that can be compared for equality
checksTwice xs = filter (\x -> occursTwice x xs) xs

或者,如果您愿意(尽管收益值得商)),则以“无点”样式重写lambda:

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

(这正是@ user2407038的注释中建议的答案-为“窃取”您的答案表示歉意)

就像您在Python中所做的那样,您希望仅使变量lst仅对checksTwice函数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指出的那样,与您想要的行为相比,这仍然存在一个错误。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM