I'm very new to Haskell and I was trying to implement a DFT which is very imperative into Haskell and I wanted to get a feedback. More specially how can I avoid so many helper functions and I avoid limiting to Double
everywhere. Thank you.
My DFT algorithm:
void dft(double[] inreal , double[] inimag, double[] outreal, double[] outimag) {
int n = inreal.length;
for (int k = 0; k < n; k++) { // For each output element
double sumreal = 0;
double sumimag = 0;
for (int t = 0; t < n; t++) { // For each input element
double angle = 2 * Math.PI * t * k / n;
sumreal += inreal[t] * Math.cos(angle) + inimag[t] * Math.sin(angle);
sumimag += -inreal[t] * Math.sin(angle) + inimag[t] * Math.cos(angle);
}
outreal[k] = sumreal;
outimag[k] = sumimag;
}
}
My Haskell code:
-- Length of the array
ownLength :: [t] -> Int
ownLength [] = 0
ownLength (_: xs) = 1 + ownLength xs
dft_resolve_nested :: [((Double, Double), Double)] -> Double -> Int -> [(Double, Double)]
dft_resolve_nested [] _ _ = []
dft_resolve_nested (((x, y), t) : xs) k n = do
let angle = 2.0 * pi * ( t) * ( k) / (fromIntegral n)
let sumreal = x * (cos angle) + y * (sin angle)
let sumimag = - x * (sin angle) + y * (cos angle)
(sumreal, sumimag) : (dft_resolve_nested xs k n)
tuples_sum :: [(Double, Double)] -> (Double, Double)
tuples_sum [] = (0, 0)
tuples_sum ((x1, y1) : xs) = do
let (x2, y2) = tuples_sum xs
(x1 + x2, y1 + y2)
dft_resolve :: [((Double, Double), Double)] -> [(Double, Double)]
dft_resolve [] = []
dft_resolve ls = do
let n = ownLength ls
let (((x, y), k) : xs) = ls
let (xr, yr) = tuples_sum (dft_resolve_nested ls k n)
(xr, yr) : (dft_resolve xs)
dft :: [(Double, Double)] -> [(Double, Double)]
dft [] = []
dft ls = dft_resolve (zip ls [0..])
-- Main driver
main = do
print (dft [(1,2), (3,4)])
Data.Complex
. It also has the functioncis
which is the exponential function of a purely imaginary number. \$\endgroup\$