Haskell提示/为什么不能线性扩展?

Mik*_*rst 5 recursion haskell tail-recursion

我的朋友写了一个程序,它比较模具面的随机排列,找到面部分布最均匀的面孔 - 特别是当面部不仅仅是一个序列时.

我将他的程序翻译成了haskell,因为我一直在寻找一个理由来谈论别人的耳朵,看看有多酷.但是,我对haskell并不是很精通(我花了很长时间才写出它并经历了几次巨大的重构)所以我有两个问题.

  1. 他在优化他的版本方面一直很重要,而且速度不是很快,并且不能线性扩展.我搞砸了一些尾递归还是某种更大的问题?
  2. 由此产生的代码实际上并不像我预测的那样优雅.我知道这不是一个讨论板,但如果你有任何关于如何简化它的想法我很满意

这是最相关的代码:

-- _CENTERS :: [{ x :: Float, y :: Float, z :: Float}]
-- _VALUES :: [Num]

-- Basically just (repeat $ map rand [0.._SIDES]), but never using a seed twice
randstates from = (take _SIDES (infrand from)) : randstates newseed
    where   infrand seed = seed : infrand (shuffle seed)
            newseed      = (infrand from) !! (_SIDES + 1)

-- yates shuffle
yates _ (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) order

arrangements 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 !! s

variance arr = sum $ map perside (matrix arr)
        where   perside s = (sum s - mean) ^ 2
                mean      = (sum (concat $ matrix arr)) / (sides + 1)
                sides     = fromInteger $ toInteger _SIDES

maxDistr = maximumBy (\a b -> variance a `compare` variance b)
Run Code Online (Sandbox Code Playgroud)

主要基本上就是

print $ maxDistr $ take _TRIALS $ arrangements seed
Run Code Online (Sandbox Code Playgroud)

scl*_*clv 1

正如评论所指出的,它不能像索引到列表中那样线性缩放O(index)。您将需要转向数组结构才能开始看到改进。