ruby while循环转换为haskell

时间:2014-07-21 10:30:20

标签: haskell

我刚刚开始学习一些Haskell和函数编程,但我发现很难掌握它:)

我正在尝试将一小段ruby代码翻译成Haskell(因为我喜欢概念函数编程和Haskell提出的甚至更多因为我来自数学领域而Haskell似乎非常数学化):

class Integer
  def factorial
    f = 1; for i in 1..self; f *= i; end; f
  end
end

boundary = 1000
m = 0

# Brown Numbers - pair of integers (m,n) where n factorial is equal with square root of m

while m <= boundary

    n = 0

    while n <= boundary
        puts "(#{m},#{n})" if ((n.factorial + 1) == (m ** 2)) 
        n += 1
    end

    m += 1
end

我只能弄清楚如何做阶乘:

let factorial n = product [1..n]

我无法弄清楚如何在Haskell中执行while循环或等效操作,即使我发现了一些让我感到困惑的例子。

这个想法是循环从0(或1)开始并继续(增量为1),直到它到达边界(在我的代码中为1000)。存在边界的原因是因为我正在考虑启动执行相同操作的并行任务但是在不同的时间间隔,因此我期望的结果返回得更快(一个操作将在1上完成{{1} },另一个1000010000等。)

如果有人能帮忙解决这个问题,我将非常感激:)

2 个答案:

答案 0 :(得分:8)

试试这个:

let results =  [(x,y) | x <- [1..1000], y <- [1..1000] ,1 + fac x == y*y]
               where fac n = product [1..n]

这是列表理解。更多关于here

将其映射到您的Ruby代码,

  1. mn中的嵌套循环已替换为xy。基本上,在指定范围内对xy的值进行迭代(在本例中为1到1000)。
  2. 最后的检查是获取布朗数字的过滤条件。
  3. where允许我们创建辅助函数来计算阶乘。
  4. 请注意,我们可以在适当的位置计算阶乘,而不是单独的函数,如下所示:

    (1 + product[1..x]) == y * y
    

    最终,左侧的(x,y)表示它返回一个元组(x,y)列表,这些是您的布朗数字。

    好的,这应该适用于你的.hs文件:

    results :: [(Integer, Integer)] --Use instead of `Int` to fix overflow issue
    results =  [(x,y) | x <- [1..1000], y <- [1..1000] , fac x == y*y]
            where fac n = product [1..n]
    

答案 1 :(得分:0)

要添加到shree.pat18的答案,也许您可​​以尝试的练习是将Haskell解决方案转换回Ruby。它应该是可能的,因为Ruby的范围是Enumerator::LazyEnumerable#flat_map。以下重写的Haskell解决方案应该有所帮助:

import Data.List (concatMap)

results :: [(Integer, Integer)]
results = concatMap (\x -> concatMap (\y -> test x y) [1..1000]) [1..1000]
    where test x y = if fac x == y*y then [(x,y)] else []
          fac n = product [1..n]

请注意,Haskell concatMap或多或少与Ruby Enumerable#flat_map相同。