27
27
28
28
module Data.Vector.Unboxed.Base (
29
29
MVector (.. ), IOVector , STVector , Vector (.. ), Unbox ,
30
- UnboxViaPrim (.. ), As (.. ), IsoUnbox (.. )
30
+ UnboxViaPrim (.. ), As (.. ), IsoUnbox (.. ),
31
+ DoNotUnboxLazy (.. ), DoNotUnboxNormalForm (.. ), DoNotUnboxStrict (.. )
31
32
) where
32
33
33
34
import qualified Data.Vector.Generic as G
34
35
import qualified Data.Vector.Generic.Mutable as M
36
+ import qualified Data.Vector as B
37
+ import qualified Data.Vector.Strict as S
35
38
36
39
import qualified Data.Vector.Primitive as P
37
40
@@ -41,6 +44,7 @@ import Control.DeepSeq ( NFData(rnf)
41
44
#if MIN_VERSION_deepseq(1,4,3)
42
45
, NFData1 (liftRnf )
43
46
#endif
47
+ , force
44
48
)
45
49
46
50
import Control.Monad.Primitive
@@ -764,6 +768,269 @@ instance (Unbox a, Unbox b) => G.Vector Vector (Arg a b) where
764
768
elemseq _ (Arg x y) z = G. elemseq (undefined :: Vector a ) x
765
769
$ G. elemseq (undefined :: Vector b ) y z
766
770
771
+ -- -------
772
+ -- Unboxing the boxed values
773
+ -- -------
774
+
775
+ -- | Newtype which allows to derive unbox instances for type @a@ which
776
+ -- is normally a "boxed" type. The newtype does not alter the strictness
777
+ -- semantics of the underlying type and inherits the laizness of said type.
778
+ -- For a strict newtype wrapper, see 'DoNotUnboxStrict'.
779
+ --
780
+ -- 'DoNotUnboxLazy' is intended to be unsed in conjunction with the newtype 'As'
781
+ -- and the type class 'IsoUnbox'. Here's an example which uses the following
782
+ -- explicit 'IsoUnbox' instance:
783
+ --
784
+ --
785
+ -- >>> :set -XTypeFamilies -XStandaloneDeriving -XDerivingVia
786
+ -- >>> :set -XMultiParamTypeClasses -XTypeOperators -XFlexibleInstances
787
+ -- >>> import qualified Data.Vector.Unboxed as VU
788
+ -- >>> import qualified Data.Vector.Unboxed.Mutable as VUM
789
+ -- >>> import qualified Data.Vector.Generic as VG
790
+ -- >>> import qualified Data.Vector.Generic.Mutable as VGM
791
+ -- >>> :{
792
+ -- >>> data Foo a = Foo Int a
793
+ -- >>> deriving (Eq, Ord, Show)
794
+ -- >>> instance VU.IsoUnbox (Foo a) (Int, VU.DoNotUnboxLazy a) where
795
+ -- >>> toURepr (Foo i a) = (i, VU.DoNotUnboxLazy a)
796
+ -- >>> fromURepr (i, VU.DoNotUnboxLazy a) = Foo i a
797
+ -- >>> {-# INLINE toURepr #-}
798
+ -- >>> {-# INLINE fromURepr #-}
799
+ -- >>> newtype instance VU.MVector s (Foo a) = MV_Foo (VU.MVector s (Int, VU.DoNotUnboxLazy a))
800
+ -- >>> newtype instance VU.Vector (Foo a) = V_Foo (VU.Vector (Int, VU.DoNotUnboxLazy a))
801
+ -- >>> deriving via (Foo a `VU.As` (Int, VU.DoNotUnboxLazy a)) instance VGM.MVector VUM.MVector (Foo a)
802
+ -- >>> deriving via (Foo a `VU.As` (Int, VU.DoNotUnboxLazy a)) instance VG.Vector VU.Vector (Foo a)
803
+ -- >>> instance VU.Unbox (Foo a)
804
+ -- >>> :}
805
+ --
806
+ -- >>> VU.fromListN 3 [ Foo 4 "Haskell's", Foo 8 "strong", Foo 16 "types" ]
807
+ -- [Foo 4 "Haskell's",Foo 8 "strong",Foo 16 "types"]
808
+ --
809
+ -- @since 0.13.2.0
810
+ newtype DoNotUnboxLazy a = DoNotUnboxLazy a
811
+
812
+ newtype instance MVector s (DoNotUnboxLazy a ) = MV_DoNotUnboxLazy (B. MVector s a )
813
+ newtype instance Vector (DoNotUnboxLazy a ) = V_DoNotUnboxLazy (B. Vector a )
814
+
815
+ instance M. MVector MVector (DoNotUnboxLazy a ) where
816
+ {-# INLINE basicLength #-}
817
+ {-# INLINE basicUnsafeSlice #-}
818
+ {-# INLINE basicOverlaps #-}
819
+ {-# INLINE basicUnsafeNew #-}
820
+ {-# INLINE basicInitialize #-}
821
+ {-# INLINE basicUnsafeReplicate #-}
822
+ {-# INLINE basicUnsafeRead #-}
823
+ {-# INLINE basicUnsafeWrite #-}
824
+ {-# INLINE basicClear #-}
825
+ {-# INLINE basicSet #-}
826
+ {-# INLINE basicUnsafeCopy #-}
827
+ {-# INLINE basicUnsafeGrow #-}
828
+ basicLength = coerce $ M. basicLength @ B. MVector @ a
829
+ basicUnsafeSlice = coerce $ M. basicUnsafeSlice @ B. MVector @ a
830
+ basicOverlaps = coerce $ M. basicOverlaps @ B. MVector @ a
831
+ basicUnsafeNew = coerce $ M. basicUnsafeNew @ B. MVector @ a
832
+ basicInitialize = coerce $ M. basicInitialize @ B. MVector @ a
833
+ basicUnsafeReplicate = coerce $ M. basicUnsafeReplicate @ B. MVector @ a
834
+ basicUnsafeRead = coerce $ M. basicUnsafeRead @ B. MVector @ a
835
+ basicUnsafeWrite = coerce $ M. basicUnsafeWrite @ B. MVector @ a
836
+ basicClear = coerce $ M. basicClear @ B. MVector @ a
837
+ basicSet = coerce $ M. basicSet @ B. MVector @ a
838
+ basicUnsafeCopy = coerce $ M. basicUnsafeCopy @ B. MVector @ a
839
+ basicUnsafeMove = coerce $ M. basicUnsafeMove @ B. MVector @ a
840
+ basicUnsafeGrow = coerce $ M. basicUnsafeGrow @ B. MVector @ a
841
+
842
+ instance G. Vector Vector (DoNotUnboxLazy a ) where
843
+ {-# INLINE basicUnsafeFreeze #-}
844
+ {-# INLINE basicUnsafeThaw #-}
845
+ {-# INLINE basicLength #-}
846
+ {-# INLINE basicUnsafeSlice #-}
847
+ {-# INLINE basicUnsafeIndexM #-}
848
+ {-# INLINE elemseq #-}
849
+ basicUnsafeFreeze = coerce $ G. basicUnsafeFreeze @ B. Vector @ a
850
+ basicUnsafeThaw = coerce $ G. basicUnsafeThaw @ B. Vector @ a
851
+ basicLength = coerce $ G. basicLength @ B. Vector @ a
852
+ basicUnsafeSlice = coerce $ G. basicUnsafeSlice @ B. Vector @ a
853
+ basicUnsafeIndexM = coerce $ G. basicUnsafeIndexM @ B. Vector @ a
854
+ basicUnsafeCopy = coerce $ G. basicUnsafeCopy @ B. Vector @ a
855
+ elemseq _ = seq
856
+
857
+ instance Unbox (DoNotUnboxLazy a )
858
+
859
+ -- | Newtype which allows to derive unbox instances for type @a@ which
860
+ -- is normally a "boxed" type. The newtype stictly evaluates the wrapped values
861
+ -- ensuring that the unboxed vector contains no (direct) thunks.
862
+ -- For a less strict newtype wrapper, see 'DoNotUnboxLazy'.
863
+ -- For a more strict newtype wrapper, see 'DoNotUnboxNormalForm'.
864
+ --
865
+ -- 'DoNotUnboxStrict' is intended to be unsed in conjunction with the newtype 'As'
866
+ -- and the type class 'IsoUnbox'. Here's an example which uses the following
867
+ -- explicit 'IsoUnbox' instance:
868
+ --
869
+ --
870
+ -- >>> :set -XBangPatterns -XTypeFamilies -XStandaloneDeriving -XDerivingVia
871
+ -- >>> :set -XMultiParamTypeClasses -XTypeOperators -XFlexibleInstances
872
+ -- >>> import qualified Data.Vector.Unboxed as VU
873
+ -- >>> import qualified Data.Vector.Unboxed.Mutable as VUM
874
+ -- >>> import qualified Data.Vector.Generic as VG
875
+ -- >>> import qualified Data.Vector.Generic.Mutable as VGM
876
+ -- >>> :{
877
+ -- >>> data Bar a = Bar Int a
878
+ -- >>> deriving Show
879
+ -- >>> instance VU.IsoUnbox (Bar a) (Int, VU.DoNotUnboxStrict a) where
880
+ -- >>> toURepr (Bar i !a) = (i, VU.DoNotUnboxStrict a)
881
+ -- >>> fromURepr (i, VU.DoNotUnboxStrict a) = Bar i a
882
+ -- >>> {-# INLINE toURepr #-}
883
+ -- >>> {-# INLINE fromURepr #-}
884
+ -- >>> newtype instance VU.MVector s (Bar a) = MV_Bar (VU.MVector s (Int, VU.DoNotUnboxStrict a))
885
+ -- >>> newtype instance VU.Vector (Bar a) = V_Bar (VU.Vector (Int, VU.DoNotUnboxStrict a))
886
+ -- >>> deriving via (Bar a `VU.As` (Int, VU.DoNotUnboxStrict a)) instance VGM.MVector VUM.MVector (Bar a)
887
+ -- >>> deriving via (Bar a `VU.As` (Int, VU.DoNotUnboxStrict a)) instance VG.Vector VU.Vector (Bar a)
888
+ -- >>> instance VU.Unbox (Bar a)
889
+ -- >>> :}
890
+ --
891
+ -- >>> VU.fromListN 3 [ Bar 3 "Bye", Bar 2 "for", Bar 1 "now" ]
892
+ -- [Bar 3 "Bye",Bar 2 "for",Bar 1 "now"]
893
+ --
894
+ -- @since 0.13.2.0
895
+ newtype DoNotUnboxStrict a = DoNotUnboxStrict a
896
+
897
+ newtype instance MVector s (DoNotUnboxStrict a ) = MV_DoNotUnboxStrict (S. MVector s a )
898
+ newtype instance Vector (DoNotUnboxStrict a ) = V_DoNotUnboxStrict (S. Vector a )
899
+
900
+ instance M. MVector MVector (DoNotUnboxStrict a ) where
901
+ {-# INLINE basicLength #-}
902
+ {-# INLINE basicUnsafeSlice #-}
903
+ {-# INLINE basicOverlaps #-}
904
+ {-# INLINE basicUnsafeNew #-}
905
+ {-# INLINE basicInitialize #-}
906
+ {-# INLINE basicUnsafeReplicate #-}
907
+ {-# INLINE basicUnsafeRead #-}
908
+ {-# INLINE basicUnsafeWrite #-}
909
+ {-# INLINE basicClear #-}
910
+ {-# INLINE basicSet #-}
911
+ {-# INLINE basicUnsafeCopy #-}
912
+ {-# INLINE basicUnsafeGrow #-}
913
+ basicLength = coerce $ M. basicLength @ S. MVector @ a
914
+ basicUnsafeSlice = coerce $ M. basicUnsafeSlice @ S. MVector @ a
915
+ basicOverlaps = coerce $ M. basicOverlaps @ S. MVector @ a
916
+ basicUnsafeNew = coerce $ M. basicUnsafeNew @ S. MVector @ a
917
+ basicInitialize = coerce $ M. basicInitialize @ S. MVector @ a
918
+ basicUnsafeReplicate = coerce $ M. basicUnsafeReplicate @ S. MVector @ a
919
+ basicUnsafeRead = coerce $ M. basicUnsafeRead @ S. MVector @ a
920
+ basicUnsafeWrite = coerce $ M. basicUnsafeWrite @ S. MVector @ a
921
+ basicClear = coerce $ M. basicClear @ S. MVector @ a
922
+ basicSet = coerce $ M. basicSet @ S. MVector @ a
923
+ basicUnsafeCopy = coerce $ M. basicUnsafeCopy @ S. MVector @ a
924
+ basicUnsafeMove = coerce $ M. basicUnsafeMove @ S. MVector @ a
925
+ basicUnsafeGrow = coerce $ M. basicUnsafeGrow @ S. MVector @ a
926
+
927
+ instance G. Vector Vector (DoNotUnboxStrict a ) where
928
+ {-# INLINE basicUnsafeFreeze #-}
929
+ {-# INLINE basicUnsafeThaw #-}
930
+ {-# INLINE basicLength #-}
931
+ {-# INLINE basicUnsafeSlice #-}
932
+ {-# INLINE basicUnsafeIndexM #-}
933
+ {-# INLINE elemseq #-}
934
+ basicUnsafeFreeze = coerce $ G. basicUnsafeFreeze @ S. Vector @ a
935
+ basicUnsafeThaw = coerce $ G. basicUnsafeThaw @ S. Vector @ a
936
+ basicLength = coerce $ G. basicLength @ S. Vector @ a
937
+ basicUnsafeSlice = coerce $ G. basicUnsafeSlice @ S. Vector @ a
938
+ basicUnsafeIndexM = coerce $ G. basicUnsafeIndexM @ S. Vector @ a
939
+ basicUnsafeCopy = coerce $ G. basicUnsafeCopy @ S. Vector @ a
940
+ elemseq _ = seq
941
+
942
+ instance Unbox (DoNotUnboxStrict a )
943
+
944
+ -- | Newtype which allows to derive unbox instances for type @a@ which
945
+ -- is normally a "boxed" type. The newtype stictly evaluates the wrapped values
946
+ -- via thier requisite 'NFData' instance, ensuring that the unboxed vector
947
+ -- contains only values reduced to normal form.
948
+ -- For a less strict newtype wrappers, see 'DoNotUnboxLazy' and 'DoNotUnboxStrict'.
949
+ --
950
+ -- 'DoNotUnboxNormalForm' is intended to be unsed in conjunction with the newtype 'As'
951
+ -- and the type class 'IsoUnbox'. Here's an example which uses the following
952
+ -- explicit 'IsoUnbox' instance:
953
+ --
954
+ --
955
+ -- >>> :set -XTypeFamilies -XStandaloneDeriving -XDerivingVia
956
+ -- >>> :set -XMultiParamTypeClasses -XTypeOperators -XFlexibleInstances
957
+ -- >>> import qualified Data.Vector.Unboxed as VU
958
+ -- >>> import qualified Data.Vector.Unboxed.Mutable as VUM
959
+ -- >>> import qualified Data.Vector.Generic as VG
960
+ -- >>> import qualified Data.Vector.Generic.Mutable as VGM
961
+ -- >>> import qualified Control.DeepSeq as NF
962
+ -- >>> :{
963
+ -- >>> data Baz a = Baz Int a
964
+ -- >>> deriving Show
965
+ -- >>> instance NF.NFData a => VU.IsoUnbox (Baz a) (Int, VU.DoNotUnboxNormalForm a) where
966
+ -- >>> toURepr (Baz i a) = (i, VU.DoNotUnboxNormalForm $ NF.force a)
967
+ -- >>> fromURepr (i, VU.DoNotUnboxNormalForm a) = Baz i a
968
+ -- >>> {-# INLINE toURepr #-}
969
+ -- >>> {-# INLINE fromURepr #-}
970
+ -- >>> newtype instance VU.MVector s (Baz a) = MV_Baz (VU.MVector s (Int, VU.DoNotUnboxNormalForm a))
971
+ -- >>> newtype instance VU.Vector (Baz a) = V_Baz (VU.Vector (Int, VU.DoNotUnboxNormalForm a))
972
+ -- >>> deriving via (Baz a `VU.As` (Int, VU.DoNotUnboxNormalForm a)) instance NF.NFData a => VGM.MVector VUM.MVector (Baz a)
973
+ -- >>> deriving via (Baz a `VU.As` (Int, VU.DoNotUnboxNormalForm a)) instance NF.NFData a => VG.Vector VU.Vector (Baz a)
974
+ -- >>> instance NF.NFData a => VU.Unbox (Baz a)
975
+ -- >>> :}
976
+ --
977
+ -- >>> VU.fromListN 3 [ Baz 3 "Fully", Baz 9 "evaluated", Baz 27 "data" ]
978
+ -- [Baz 3 "Fully",Baz 9 "evaluated",Baz 27 "data"]
979
+ --
980
+ -- @since 0.13.2.0
981
+ newtype DoNotUnboxNormalForm a = DoNotUnboxNormalForm a
982
+
983
+ newtype instance MVector s (DoNotUnboxNormalForm a ) = MV_DoNotUnboxNormalForm (S. MVector s a )
984
+ newtype instance Vector (DoNotUnboxNormalForm a ) = V_DoNotUnboxNormalForm (S. Vector a )
985
+
986
+ instance NFData a => M. MVector MVector (DoNotUnboxNormalForm a ) where
987
+ {-# INLINE basicLength #-}
988
+ {-# INLINE basicUnsafeSlice #-}
989
+ {-# INLINE basicOverlaps #-}
990
+ {-# INLINE basicUnsafeNew #-}
991
+ {-# INLINE basicInitialize #-}
992
+ {-# INLINE basicUnsafeReplicate #-}
993
+ {-# INLINE basicUnsafeRead #-}
994
+ {-# INLINE basicUnsafeWrite #-}
995
+ {-# INLINE basicClear #-}
996
+ {-# INLINE basicSet #-}
997
+ {-# INLINE basicUnsafeCopy #-}
998
+ {-# INLINE basicUnsafeGrow #-}
999
+ basicLength = coerce $ M. basicLength @ S. MVector @ a
1000
+ basicUnsafeSlice = coerce $ M. basicUnsafeSlice @ S. MVector @ a
1001
+ basicOverlaps = coerce $ M. basicOverlaps @ S. MVector @ a
1002
+ basicUnsafeNew = coerce $ M. basicUnsafeNew @ S. MVector @ a
1003
+ basicInitialize = coerce $ M. basicInitialize @ S. MVector @ a
1004
+ basicUnsafeReplicate = coerce (\ i x -> M. basicUnsafeReplicate @ S. MVector @ a i (force x))
1005
+ basicUnsafeRead = coerce $ M. basicUnsafeRead @ S. MVector @ a
1006
+ basicUnsafeWrite = coerce (\ v i x -> M. basicUnsafeWrite @ S. MVector @ a v i (force x))
1007
+ basicClear = coerce $ M. basicClear @ S. MVector @ a
1008
+ basicSet = coerce (\ v x -> M. basicSet @ S. MVector @ a v (force x))
1009
+ basicUnsafeCopy = coerce $ M. basicUnsafeCopy @ S. MVector @ a
1010
+ basicUnsafeMove = coerce $ M. basicUnsafeMove @ S. MVector @ a
1011
+ basicUnsafeGrow = coerce $ M. basicUnsafeGrow @ S. MVector @ a
1012
+
1013
+ instance NFData a => G. Vector Vector (DoNotUnboxNormalForm a ) where
1014
+ {-# INLINE basicUnsafeFreeze #-}
1015
+ {-# INLINE basicUnsafeThaw #-}
1016
+ {-# INLINE basicLength #-}
1017
+ {-# INLINE basicUnsafeSlice #-}
1018
+ {-# INLINE basicUnsafeIndexM #-}
1019
+ {-# INLINE elemseq #-}
1020
+ basicUnsafeFreeze = coerce $ G. basicUnsafeFreeze @ S. Vector @ a
1021
+ basicUnsafeThaw = coerce $ G. basicUnsafeThaw @ S. Vector @ a
1022
+ basicLength = coerce $ G. basicLength @ S. Vector @ a
1023
+ basicUnsafeSlice = coerce $ G. basicUnsafeSlice @ S. Vector @ a
1024
+ basicUnsafeIndexM = coerce $ G. basicUnsafeIndexM @ S. Vector @ a
1025
+ basicUnsafeCopy = coerce $ G. basicUnsafeCopy @ S. Vector @ a
1026
+ elemseq _ x y = rnf (coerce x :: a ) `seq` y
1027
+
1028
+ instance NFData a => Unbox (DoNotUnboxNormalForm a )
1029
+
1030
+ instance NFData a => NFData (DoNotUnboxNormalForm a ) where
1031
+ {-# INLINE rnf #-}
1032
+ rnf = rnf . coerce @ (DoNotUnboxNormalForm a ) @ a
1033
+
767
1034
deriveNewtypeInstances(() , Any , Bool , Any , V_Any , MV_Any )
768
1035
deriveNewtypeInstances(() , All , Bool , All , V_All , MV_All )
769
1036
0 commit comments