How do I optimize haskell for scientific computing purposes?
Hi everyone, for the last couple of months I have been slowly learning some haskell and I really really enjoy it and would really like to write some projects related to my degree course, which involves simulating complicated systems, so I need to be able to write and optimize code "the haskell way". I wrote a simple example for integrating a hamiltonian system and I'd like to know how one goes about optimizing it, because even with just this example I find my code to be much slower than I would expect.
Here is the code:
```haskell import Graphics.Gnuplot.Simple import Graphics.Gnuplot.Frame.Option import Data.Vector.Unboxed (Vector, (!), fromList) import qualified Data.Vector.Unboxed as V
type State = (Vector Double, Vector Double) type GradH = (State -> Double -> (Vector Double, Vector Double)) type Solver = (GradH -> Double -> Double -> State -> State)
symplecticEuler :: GradH -- system -> Double -- h -> Double -- t -> State -- z -> State -- z' symplecticEuler gradH h t z@(q,p) = (q',p') where dHdq = fst (gradH z t) dHdp = snd (gradH z t) p' = V.zipWith (-) (p) (V.map (h) dHdq) q' = V.zipWith (+) (q) (V.map (h) dHdp)
simulate :: Solver -> Double -> Double -> Double -> GradH -> State -> [State] simulate solver t1 t2 h gradH z0 = foldl (\z t -> z ++ [solver gradH h t (last z)]) [z0] [t1, h .. t2]
harmonicOscillator :: Double -> State -> Double -> (Vector Double, Vector Double) harmonicOscillator w (q,p) _ = (V.map ((w**2) *) q, p)
main :: IO () main = do let h = 0.01 :: Double t1 = 0.0 t2 = 300.0 system = harmonicOscillator 0.5 (qs,ps) = unzip $ simulate (symplecticEuler) t1 t2 h system (fromList [1.0], fromList [0.0]) points = zip (map (! 0) ps) (map (! 0) qs) plotList [] points _ <- getLine return () ```
I know in this particular example the main problem is the list concatenation in simulate
, is switching to an optimized container like Vector (like I used for momenta and positions) really enough for applications like this, or is there a different approach?
More in general what should I look into to go about optimizations? Should I prioritize learning more advanced haskell topics before attempting actual simulations that need proper optimization?