My friend wrote a program which compares random arrangements of die faces to find the one with the most evenly distributed faces - especially when the faces are not a mere sequence.I translated his program into haskell because I've been looking for a reason to talk someone's ear off about how cool haskell is. However, I am not very proficient with haskell (it took me forever to write this and it has undergone a couple giant refactorings) and so I have two problems.he has been big on optimizing his versions, and this is not very fast, and it does not scale linearly. It goes from 415 checks/s to 97 checks/s when I go from 1000 to 20000 checks. Did I mess up some tail recursion or is it some kind of larger problem?the code that came out of this isn't actually as elegant as I had predicted. I want this to be a solid showcase of Haskell, if you have any ideas on how to simplify it I am all earsThis is the most relevant code:-- _CENTERS :: [{ x :: Float, y :: Float, z :: Float}]-- _VALUES :: [Num]-- Basically just (repeat $ map rand [0.._SIDES]), but never using a seed twicerandstates from = (take _SIDES (infrand from)) : randstates newseed    where   infrand seed = seed : infrand (shuffle seed)            newseed      = (infrand from) !! (_SIDES + 1)-- yates shuffleyates _ (last:[]) = [last]yates (rand:pass) (swap:order) = choice:yates pass rorder        where   choice = order !! index                index  = (randfrom rand) `mod` (length order)                rorder = take (index) order ++ swap : drop (index + 1) orderarrangements seed = map arrange $ randstates seed        where   arrange rands = yates rands [0.._SIDES - 2]-- fns comparing arrangements --arcLength i j = 1 / (1 + _WEIGHT * acos(dot3D / _VEC_LEN_SQUARED))        where   dot3D    = apply x + apply y + apply z                apply fn = (fn i) * (fn j)matrix arr = map crosscmp arr        where   crosscmp s1  = [ value s1 * (distance s1 s2) | s2  <- arr ]                distance a b = arcLength (_CENTERS !! a) (_CENTERS !! b)                value s      = fromInteger $ _VALUES !! svariance arr = sum $ map perside (matrix arr)        where   perside s = (sum s - mean) ^ 2                mean      = (sum (concat $ matrix arr)) / (sides + 1)                sides     = fromInteger $ toInteger _SIDESmaxDistr = maximumBy (\a b -> variance a `compare` variance b)Main is basically justprint $ maxDistr $ take _TRIALS $ arrangements seed
Haskell tips/why doesnt this scale linearly?
performance;haskell;recursion