Tuesday, January 22, 2008

Simple comparison of iteration with Python and use of Map in Haskell

Here is a simple code snippet that shows the variation between how to approach problems in python and how to approach problems in haskell. More often than not, the same problem or task that you want to accomplish is the same but the methods used are going to be different. There is no question that python is an imperative language. You will tackle a problem by figuring how how to perform step 1 and then step 2, possibly N number of times. Haskell is a purely functional programming language but some like Simon Peyton Jones call Haskell "the best imperative language".


Perform the invchi2 calculation in python

example_data = [
(4.3, 6),
(2.2, 60),
(60, 2.2),
(0.3, 4),
(32.123, 20),
(12.4, 5),
(0.04, 3),
(0, 0),
(1, 1)
]
def invchi(chi, df):
m = chi / 2.0
sum = term = math.exp(-m)
for i in range(1, df//2):
term *= m / i
sum += term
return min(sum, 1.0)
if __name__ == '__main__':
print "Running InvChi Test"
for chi, df in example_data:
print "[ chi=%s df=%s ] res=%s" % (chi, df, invchi(chi, df))
print "Done"

Similar code in Haskell

exampleData :: [(Double, Double)]
exampleData = [
(4.3, 6),
(2.2, 60),
(60, 2.2),
(0.3, 4),
(32.123, 20),
(12.4, 5),
(0.04, 3),
(0, 0),
(1, 1)]

-- Inverted Chi2 formula
invChi :: Double -> Double -> Double
invChi chi df = minimum([snd newsum, 1.0])
where m = chi / 2.0
initsum = exp (-m)
trm = exp (-m)
maxrg = fromIntegral (floor (df / 2.0)) :: Double
-- Return a tuple with current sum and term, given these inputs
newsum = foldl (\(trm,sm) elm -> ((trm*(m/elm)), sm+trm))
(trm,initsum) [1..maxrg]

runBayesTest = do
putStrLn "Bayes Test: Inv Chi"
mapM_ (\x -> putStrLn $ (show x) ++ " res=" ++ (show (invChi (fst x) (snd x)))) exampleData
putStrLn "Done Bayes"

No comments: