【问题标题】:While in a loop in Haskell在 Haskell 中循环时
【发布时间】:2015-10-13 17:15:30
【问题描述】:

如何在 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 或一些运行速度更快的更好的代码来完成吗?

【问题讨论】:

    标签: loops haskell for-loop while-loop


    【解决方案1】:

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

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

    我不喜欢列表推导,尤其是对于更复杂的表达式,因此我发现您的解决方案难以阅读。主要区别在于,我存储了实际的函数值,而不是存储js 这样的f i j &gt; 0 列表。由于懒惰,这不再起作用。

    【讨论】:

      【解决方案2】:

      为了好玩,我能想到的最直接的翻译是:

      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
      

      【讨论】:

        猜你喜欢
        • 2022-12-06
        • 2013-05-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-06-08
        • 2016-01-27
        • 2020-04-04
        相关资源
        最近更新 更多