Hello,<br><br>I'm trying to write code that will take a mutable 2D array and normalize it by dividing all elements by the largest element. <br><br>I managed to write code to do this, but it seems overly complex. I could write something much simpler in Clean or C++. Most likely, my code is complex because I don't have any experience with mutable arrays in Haskell. I couldn't find any tutorials on the Internet. I'd be grateful for suggestions on simplifying the following code. Thanks.<br>
<br><br><span style="font-family: courier new,monospace;">{-# OPTIONS_GHC -fglasgow-exts -fbreak-on-exception #-}</span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">-- normalize_ary This takes a mutable array. Determines the largest</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">-- element in the array (max_elem) and then divides every element by</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">-- max_elem.</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">normalize_ary :: (Num t1,</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> Num t,</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> Ix t,</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> Ix t1,</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> MArray a e t2,</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> Ord e,</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> Fractional e,</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> Enum t,</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> Enum t1) =></span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> a (t, t1) e -> t2 ()</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">normalize_ary ary = </span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> do </span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> -- The following two commented out lines of code show my first</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> -- attempt at determining a value for max_elem. However, this</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> -- produces a stack overflow.</span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> -- elem_ary <- getElems ary </span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> -- let max_elem = foldl1 max elem_ary</span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> max_elem <- calc_max_2d_elem ary</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> max_elem `seq` map_in_place_2d_arr (\x -> x / max_elem) ary</span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">map_in_place_2d_arr :: (MArray a e t, Enum t2, Enum t1, Ix t1, Ix t2) =></span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> (e -> e) -> a (t1, t2) e -> t ()</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">map_in_place_2d_arr fn arr = ret</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> where </span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> ret = do ((i1,j1),(i2,j2)) <- getBounds arr</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> ( mapM_ (\i -> do v <- readArray arr i</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> writeArray arr i (fn v) )</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> [(i,j) | i <- [i1..i2], j <- [j1..j2]])</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">calc_max_2d_elem :: (Ord t, MArray a t t1, Ix t2, Ix t3, Num t3, Num t2) =></span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> a (t3, t2) t -> t1 t</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">calc_max_2d_elem arr = </span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> do m <- readArray arr (0,0)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> (_,(i_max, j_max)) <- getBounds arr</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> let calc_max_loop arr m (i,j)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> | j == j_max = return m</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> | otherwise = do e <- readArray arr (i,j)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> let m2 = max e m</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> m2 `seq` calc_max_loop arr m2 nxt_idx</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> where nxt_idx | i == i_max - 1 = (0,j+1)</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;"> | otherwise = (i+1,j)</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;"> calc_max_loop arr m (0,0)</span><br style="font-family: courier new,monospace;">
<br>