OC Test your knowledge of Haskell's array primitives
Consider the following two implementations of a 'map' function for arrays. Can you guess which one of them is the fastest without running them? (Please ignore the uses of unsafeCoerce
:P)
Required imports:
import Data.Primitive.Array
import Control.Monad.ST.Strict
import Unsafe.Coerce
Version 1:
mapArray1 :: forall a b. (a -> b) -> Array a -> Array b
mapArray1 f arr = runST $
let n = length arr in
thawArray arr 0 n >>= \m ->
let
go i
| i < n = do
x <- readArray m i
writeArray m i $! unsafeCoerce @b @a (f x)
go (i + 1)
| otherwise = do
arr' <- unsafeFreezeArray m
return (unsafeCoerce @(Array a) @(Array b) arr')
in
go 0
Version 2:
mapArray2 :: forall a b. (a -> b) -> Array a -> Array b
mapArray2 f arr =
let n = length arr in
createArray n (unsafeCoerce @() @b ()) $ \m ->
let
go i
| i < n = do
writeArray m i $! f $! indexArray arr i
go (i + 1)
| otherwise = return ()
in
go 0
Add comment