this post was submitted on 17 Aug 2023
2 points (100.0% liked)

Haskell

5 readers
1 users here now

**The Haskell programming language community.** Daily news and info about all things Haskell related: practical stuff, theory, types, libraries, jobs, patches, releases, events and conferences and more... ### Links - Get Started with Haskell

founded 2 years ago
 

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

you are viewing a single comment's thread
view the rest of the comments
[–] jaror@kbin.social 1 points 2 years ago* (last edited 2 years ago)

You may want to use the Hackage page of the Data.Primitive.Array module: https://hackage.haskell.org/package/primitive-0.8.0.0/docs/Data-Primitive-Array.html

Some relevant functions:

createArray :: Int -> a -> (forall s. MutableArray s a -> ST s ()) -> Array a

Create an array of the given size with a default value, apply the monadic function and freeze the result. If the size is 0, return emptyArray (rather than a new copy thereof).

createArray 0 _ _ = emptyArray
createArray n x f = runArray $ do
  mary &lt;- newArray n x
  f mary
  pure mary

thawArray
  :: PrimMonad m	 
  => Array a -- ^ source
  -> Int     -- ^ offset
  -> Int     -- ^ length
  -> m (MutableArray (PrimState m) a)	 

Create a mutable array from a slice of an immutable array.

This operation makes a copy of the specified slice, so it is safe to use the immutable array afterward.

Note: The provided array should contain the full subrange specified by the two Ints, but this is not checked.