我刚刚开始学习函数式编程和Haskell,我甚至不太了解语法及其工作原理,因为它与我之前习惯的非常不同(例如ruby,php,C#或node)这些是OOP语言 - 或多或少)。
我正在尝试整理一个小程序来检查Brocard's Problem或所谓的 Brown Numbers 的解决方案,我首先在ruby中创建了一个草稿,但我发现Haskell是更适合做数学表达式。我以前问过question,我很快就得到了如何将我的ruby代码翻译成Haskell的答案:
results :: [(Integer, Integer)] --Use instead of `Int` to fix overflow issue
results = [(x,y) | x <- [1..1000], y <- [1..1000] , 1 + fac x == y*y]
where fac n = product [1..n]
我稍微改变了一下,所以我可以从我想要的任何数字运行相同的操作,因为以上操作将从1
到1000
或任何硬编码的数字,但我想能够决定它应该经过的间隔,ergo:
pairs :: (Integer, Integer) -> [(Integer, Integer)]
pairs (lower, upper) = [(m, n) | m <- [lower..upper], n <- [lower..upper], 1 + factorial n == m*m] where factorial n = product [1..n]
我问这个问题的原因是我在考虑是否可以并行(和/或在多个线程和/或核心上)运行此操作,并将结果附加到同一个变量。
我还没有理解Haskell或线程模型中的并行处理,但在ruby中,线程模型如何工作的一个很好的例子就像this:
def func1
i=0
while i<=2
puts "func1 at: #{Time.now}"
sleep(2)
i=i+1
end
end
def func2
j=0
while j<=2
puts "func2 at: #{Time.now}"
sleep(1)
j=j+1
end
end
puts "Started At #{Time.now}"
t1=Thread.new{func1()}
t2=Thread.new{func2()}
t1.join
t2.join
puts "End at #{Time.now}"
就我而言,func1
和func2
将是在不同时间间隔(results
)计算的相同函数[1..1000] -> [i..j]
。
我很感激一些帮助,因为我现在无法自己做这件事:)
答案 0 :(得分:2)
Parallel and Concurrent Programming in Haskell有很多很好的信息,async是一个很好的库。
但是在底层,你会发现forkIO
来启动一个新的轻量级线程。
当然,并发,而不是确定性并行,parallel就是这个库,本书也对此进行了介绍。
您的示例转换为:
import Data.Time.Clock (getCurrentTime)
main = do
start <- getCurrentTime
putStr "Started At " >> print start
_ <- forkIO func1
_ <- forkIO func2
end <- getCurrentTime
putStr "End at " >> print end
func1 = helper "func1" 2
func2 = helper "func2" 1
helper name sleepTime = go 0
where
go 3 = return ()
go n = do
now <- getCurrentTime
putStr name >> putStr " at: " >> print now
threadDelay sleepTime
go $ succ n
我建议学习上面提到的并行和/或异步库,而不是编写自己的线程内容,至少最初是这样。
这是使用并行在8-ish处理器上运行测试的一个不太好的例子:
import Control.Parallel.Strategies
factorial = product . enumFromTo 1
pairs (lower, upper) = map fst . filter snd . withStrategy sparkTest
$ [ ((m, n), b)
| m <- [lower..upper]
, n <- [lower..upper]
, let b = 1 + factorial n == m*m
]
sparkTest = evalBuffer 8 $ evalTuple2 rseq rpar