而在Haskell的循环中

时间:2015-10-13 17:15:31

标签: loops haskell for-loop while-loop

如何在Haskell中编写以下伪代码?

x=0
for (i from 0 to 100):
    j=0
    while ( f(i,j) >0 ):
      x+= f(i,j)
      j+=1

f一些不重要的功能。)

我想出了类似的东西:

a= [x| i<-[0..100], let s = takeWhile (\k-> (f i k > 0)) [0..],
        j<- s, let x = f i j ]

然后Sum a完成工作,但我需要计算f i j两次,这有点多余。

这可以用f只计算一次或更好的代码运行得更快吗?

2 个答案:

答案 0 :(得分:2)

这是一种只为每对计算f一次的方法:

inner i = sum $ takeWhile (> 0) $ map (f i) [0..]
x= sum $ map inner [0..100]

我不喜欢列表推导,特别是对于更复杂的表达式,所以我发现你的解决方案很难阅读。主要区别在于,我存储了实际的函数值,而不是存储j的{​​{1}}列表。由于懒惰,这不再有用了。

答案 1 :(得分:0)

为了获得乐趣,我能想到的最直接的翻译是:

f i j = 100 - i - j

test x =
  foldr (\i ->
      foldr (\j g ->
          let y = f i j in
          if y > 0 then g . (+ y) else id
        ) id [0..]
    ) x [0..100]

x = test 0

或者与一些帮助者:

f i j = 100 - i - j

for :: (Enum i) => i -> i -> (i -> a -> a) -> a -> a
for i1 i2 f x = foldr f x [i1..i2]

while :: i -> (i -> i) -> (i -> Bool) -> (i -> a -> a) -> a -> a
while i s p f x =
  foldr (\i g x ->
      if p i then g (f i x) else x
    ) id (iterate s i) x

test =
  for 0 100 $ \i ->
    while 0 (+ 1) (\j -> f i j > 0) $ \j x ->
      x + f i j

x = test 0