如何在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
只计算一次或更好的代码运行得更快吗?
答案 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