2015-10-13 43 views
0

如何在Haskell中对以下伪代码进行编码?在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

这里的一种方式,只为每对计算f一次:我不喜欢列表理解

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

,尤其是对于更复杂的表达式,所以我发现您的解决方案难以阅读。主要区别在于,我不是存储j s的列表,而是存储了实际的函数值f i j > 0。由于懒惰,这没有更多的工作。

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