Skip to content

Commit d01fdd2

Browse files
committed
Heterogeneous array creation
Create arbitrarily many arrays of arbitrarily many types from one `ST` action. Closes #103
1 parent c40a0d5 commit d01fdd2

File tree

2 files changed

+117
-2
lines changed

2 files changed

+117
-2
lines changed

Data/Primitive/Array.hs

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
{-# LANGUAGE CPP, MagicHash, UnboxedTuples, DeriveDataTypeable, BangPatterns #-}
22
{-# LANGUAGE RankNTypes #-}
33
{-# LANGUAGE TypeFamilies #-}
4+
#if __GLASGOW_HASKELL__ >= 708
5+
{-# LANGUAGE PolyKinds #-}
6+
#endif
47

58
-- |
69
-- Module : Data.Primitive.Array
@@ -17,7 +20,7 @@ module Data.Primitive.Array (
1720
Array(..), MutableArray(..),
1821

1922
newArray, readArray, writeArray, indexArray, indexArrayM,
20-
freezeArray, thawArray, runArray,
23+
freezeArray, thawArray, runArray, runArrays, runArraysHetOf,
2124
unsafeFreezeArray, unsafeThawArray, sameMutableArray,
2225
copyArray, copyMutableArray,
2326
cloneArray, cloneMutableArray,
@@ -341,7 +344,6 @@ emptyArray# _ = case emptyArray of Array ar -> ar
341344
{-# NOINLINE emptyArray# #-}
342345
#endif
343346

344-
345347
die :: String -> String -> a
346348
die fun problem = error $ "Data.Primitive.Array." ++ fun ++ ": " ++ problem
347349

@@ -798,3 +800,57 @@ instance (Typeable s, Typeable a) => Data (MutableArray s a) where
798800
toConstr _ = error "toConstr"
799801
gunfold _ _ = error "gunfold"
800802
dataTypeOf _ = mkNoRepType "Data.Primitive.Array.MutableArray"
803+
804+
-- | Create any number of arrays of the same type within an arbitrary
805+
-- 'Traversable' context. This will often be useful with traversables
806+
-- like @(c,)@, @'Either' e@, @'Compose' (c,) ('Either' e)@, and
807+
-- @'Compose' ('Either' e) (c,)@. For a more general version, see
808+
-- 'runArraysHetOf'.
809+
runArrays
810+
:: Traversable t
811+
=> (forall s. ST s (t (MutableArray s a)))
812+
-> t (Array a)
813+
runArrays m = runST $ m >>= traverse unsafeFreezeArray
814+
815+
-- | Create arbitrarily many arrays that may have different types.
816+
-- For a simpler but less general version, see 'runArrays'.
817+
--
818+
-- === __Examples__
819+
--
820+
-- ==== @'runArrays'@
821+
--
822+
-- @
823+
-- newtype Ha t a v = Ha {unHa :: t (v a)}
824+
-- runArrays m = unHa $ runArraysHetOf (\f (Ha t) -> Ha <$> traverse f t) (Ha <$> m)
825+
-- @
826+
--
827+
-- ==== @unzipArray@
828+
--
829+
-- @
830+
-- unzipArray :: Array (a, b) -> (Array a, Array b)
831+
-- unzipArray ar =
832+
-- unPair $ runArraysHetOf traversePair $ do
833+
-- xs <- newArray sz undefined
834+
-- ys <- newArray sz undefined
835+
-- let go k
836+
-- | k == sz = pure (Pair (xs, ys))
837+
-- | otherwise = do
838+
-- (x,y) <- indexArrayM ar k
839+
-- writeArray xs k x
840+
-- writeArray ys k y
841+
-- go (k + 1)
842+
-- go 0
843+
-- where sz = sizeofArray ar
844+
--
845+
-- data Pair ab v where
846+
-- Pair :: {unPair :: (v a, v b)} -> Pair (a,b) v
847+
--
848+
-- traversePair :: Applicative h => (forall x. f x -> h (g x)) -> Pair ab f -> h (Pair ab g)
849+
-- traversePair f (Pair (xs, ys)) = liftA2 (\x y -> Pair (x,y)) (f xs) (f ys)
850+
-- @
851+
runArraysHetOf
852+
:: (forall h f g.
853+
(Applicative h => (forall x. f x -> h (g x)) -> t f -> h (u g))) -- ^ A rank-2 traversal
854+
-> (forall s. ST s (t (MutableArray s))) -- ^ An 'ST' action producing a rank-2 container of 'MutableArray's.
855+
-> u Array
856+
runArraysHetOf f m = runST $ m >>= f unsafeFreezeArray

Data/Primitive/SmallArray.hs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
{-# LANGUAGE DeriveDataTypeable #-}
88
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
99
{-# LANGUAGE BangPatterns #-}
10+
#if __GLASGOW_HASKELL__ >= 708
11+
{-# LANGUAGE PolyKinds #-}
12+
#endif
1013

1114
-- |
1215
-- Module : Data.Primitive.SmallArray
@@ -52,6 +55,8 @@ module Data.Primitive.SmallArray
5255
, unsafeFreezeSmallArray
5356
, thawSmallArray
5457
, runSmallArray
58+
, runSmallArrays
59+
, runSmallArraysHetOf
5560
, unsafeThawSmallArray
5661
, sizeofSmallArray
5762
, sizeofSmallMutableArray
@@ -940,3 +945,57 @@ smallArrayFromListN n l = SmallArray (Array.fromListN n l)
940945
-- | Create a 'SmallArray' from a list.
941946
smallArrayFromList :: [a] -> SmallArray a
942947
smallArrayFromList l = smallArrayFromListN (length l) l
948+
949+
-- | Create any number of arrays of the same type within an arbitrary
950+
-- 'Traversable' context. This will often be useful with traversables
951+
-- like @(c,)@, @'Either' e@, @'Compose' (c,) ('Either' e)@, and
952+
-- @'Compose' ('Either' e) (c,)@. For a more general version, see
953+
-- 'runArraysHetOf'.
954+
runSmallArrays
955+
:: Traversable t
956+
=> (forall s. ST s (t (SmallMutableArray s a)))
957+
-> t (SmallArray a)
958+
runSmallArrays m = runST $ m >>= traverse unsafeFreezeSmallArray
959+
960+
-- | Create arbitrarily many arrays that may have different types. For
961+
-- a simpler but less general version, see 'runArrays'.
962+
--
963+
-- === __Examples__
964+
--
965+
-- ==== @'runSmallArrays'@
966+
--
967+
-- @
968+
-- newtype Ha t a v = Ha {unHa :: t (v a)}
969+
-- runSmallArrays m = unHa $ runSmallArraysHetOf (\f (Ha t) -> Ha <$> traverse f t) (Ha <$> m)
970+
-- @
971+
--
972+
-- ==== @unzipSmallArray@
973+
--
974+
-- @
975+
-- unzipSmallArray :: Array (a, b) -> (Array a, Array b)
976+
-- unzipSmallArray ar =
977+
-- unPair $ runSmallArraysHetOf traversePair $ do
978+
-- xs <- newSmallArray sz undefined
979+
-- ys <- newSmallArray sz undefined
980+
-- let go k
981+
-- | k == sz = pure (Pair (xs, ys))
982+
-- | otherwise = do
983+
-- (x,y) <- indexSmallArrayM ar k
984+
-- writeSmallArray xs k x
985+
-- writeSmallArray ys k y
986+
-- go (k + 1)
987+
-- go 0
988+
-- where sz = sizeofSmallArray ar
989+
--
990+
-- data Pair ab v where
991+
-- Pair :: {unPair :: (v a, v b)} -> Pair (a,b) v
992+
--
993+
-- traversePair :: Applicative h => (forall x. f x -> h (g x)) -> Pair ab f -> h (Pair ab g)
994+
-- traversePair f (Pair (xs, ys)) = liftA2 (\x y -> Pair (x,y)) (f xs) (f ys)
995+
-- @
996+
runSmallArraysHetOf
997+
:: (forall h f g.
998+
(Applicative h => (forall x. f x -> h (g x)) -> t f -> h (u g))) -- ^ A rank-2 traversal
999+
-> (forall s. ST s (t (SmallMutableArray s))) -- ^ An 'ST' action producing a rank-2 container of 'MutableArray's.
1000+
-> u SmallArray
1001+
runSmallArraysHetOf f m = runST $ m >>= f unsafeFreezeSmallArray

0 commit comments

Comments
 (0)