{-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE Rank2Types #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-} -- | -- This module provides function for working with product types and -- comes in two variants. First works with plain product, types like -- @(a,b)@ or @data Prod = Prod A B@, etc. Second one is for -- parameterized products (it seems there's no standard name for -- them), that is types like: @data ProdF f = ProdF (f Int) (f Char)@. -- -- Most examples in this module use tuple but library is not limited -- to them in any way. They're just in base and convenient to work -- with. module Data.Vector.HFixed ( -- * HVector type classes HVector(..) , tupleSize , HVectorF(..) , tupleSizeF , ContVec , ContVecF(..) , asCVec , asCVecF -- * Plain product types -- ** Construction -- *** Simple constructor -- $construction , mk0 , mk1 , mk2 , mk3 , mk4 , mk5 -- *** Unfoldr & replicate , unfoldr , replicate , replicateM -- ** Position based functions , convert , head , tail , cons , concat -- *** Indexing , ValueAt , Index , index , set , element , elementCh , tyLookup , tyLookupF -- ** Folds & unfolds , foldr , foldl , foldMap , mapM_ -- ** Zips , zipWith , zipFold -- ** Specializations , eq , compare , rnf -- * Parametrized products -- ** Construction -- *** Simple constructors -- $construction_F , mk0F , mk1F , mk2F , mk3F , mk4F , mk5F -- *** Unfoldr & replicate , unfoldrF , replicateF , replicateNatF -- ** Conversion to\/from products , wrap , unwrap , monomorphize , monomorphizeF -- ** Functor\/Applicative like , map , mapNat , sequence , sequence_ , sequenceF , distribute , distributeF -- ** Folds and unfolds , foldrF , foldlF , foldMapF , foldrNatF , foldlNatF , foldMapNatF -- ** Zips , zipWithF , zipWithNatF , zipFoldF -- ** Reexports , Arity , ArityC , Proxy(..) ) where import Control.Applicative (Applicative(..),(<$>)) import qualified Control.DeepSeq as NF import Data.Coerce (coerce) import Data.Functor.Compose (Compose(..)) import Data.Functor.Identity (Identity(..)) import Data.Monoid (Monoid,All(..)) import Prelude ( Functor(..),Eq(..),Ord,Bool,Ordering , id,(.),($),seq) import qualified Prelude import Data.Vector.HFixed.Class hiding (cons,consF) import Data.Vector.Fixed.Cont (Peano) import qualified Data.Vector.Fixed as F import qualified Data.Vector.HFixed.Cont as C ---------------------------------------------------------------- -- Generic API ---------------------------------------------------------------- -- | Restrict type of vector to 'ContVec'. This function is useful for -- resolving type ambiguity when composing functions. For example -- following code would not compile because intermediate type is -- ambiguous: -- -- > cons 'a' . tail -- -- GHC cannot guess what type should be produced by @tail@. However -- we can fix type of intermediate vector with @asCVec@, so code -- below will work just fine: -- -- > cons 'a' . asCVec . tail asCVec :: ContVec xs -> ContVec xs asCVec = id asCVecF :: ContVecF f xs -> ContVecF f xs asCVecF = id -- | We can convert between any two vector which have same -- structure but different representations. -- -- >>> convert (1 :+ 2) :: (Double,Double) -- (1.0,2.0) convert :: (HVector v, HVector w, Elems v ~ Elems w) => v -> w {-# INLINE convert #-} convert v = inspect v construct -- | Tail of the vector. Note that in the example we only tell GHC -- that resulting value is 2-tuple via pattern matching and let -- typechecker figure out the rest. -- -- >>> case tail ('a',"aa",()) of x@(_,_) -> x -- ("aa",()) tail :: (HVector v, HVector w, (a : Elems w) ~ Elems v) => v -> w {-# INLINE tail #-} tail = C.vector . C.tail . C.cvec -- | Head of the vector -- -- >>> head ('a',"ABC") -- 'a' head :: (HVector v, Elems v ~ (a : as), Arity as) => v -> a {-# INLINE head #-} head = C.head . C.cvec -- | Prepend element to the product. -- -- >>> cons 'c' ('d','e') :: (Char,Char,Char) -- ('c','d','e') cons :: (HVector v, HVector w, Elems w ~ (a : Elems v)) => a -> v -> w {-# INLINE cons #-} cons a = C.vector . C.cons a . C.cvec -- | Concatenate two vectors -- -- >>> concat ('c','d') ('e','f') :: (Char,Char,Char,Char) -- ('c','d','e','f') concat :: ( HVector v, HVector u, HVector w , Elems w ~ (Elems v ++ Elems u) ) => v -> u -> w concat v u = C.vector $ C.concat (C.cvec v) (C.cvec u) {-# INLINE concat #-} ---------------------------------------------------------------- -- Indexing ---------------------------------------------------------------- -- | Index heterogeneous vector. -- -- >>> index (Proxy @0) ('c',"str") -- 'c' -- >>> index (Proxy @1) ('c',"str") -- "str" index :: forall n v proxy. (Index (Peano n) (Elems v), HVector v) => proxy n -- ^ Type level index -> v -- ^ Vector to index -> ValueAt (Peano n) (Elems v) {-# INLINE index #-} index _ v = C.index (C.cvec v) (Proxy @(Peano n)) -- | Set element in the vector -- -- >>> set (Proxy @0) 'X' ('_',"str") -- ('X',"str") set :: forall n v proxy. (Index (Peano n) (Elems v), HVector v) => proxy n -- ^ Type level index -> ValueAt (Peano n) (Elems v) -- ^ New value at index -> v -> v {-# INLINE set #-} set _ x = C.vector . C.set (Proxy @(Peano n)) x . C.cvec -- | Twan van Laarhoven's lens for i'th element. element :: forall n v proxy. ( Index (Peano n) (Elems v) , HVector v ) => proxy n -- ^ Type level index -> Lens' v (ValueAt (Peano n) (Elems v)) {-# INLINE element #-} element _ f v = inspect v $ lensF (Proxy @(Peano n)) f construct -- | Type changing Twan van Laarhoven's lens for i'th element. elementCh :: forall n v w a b proxy. ( Index (Peano n) (Elems v) , ValueAt (Peano n) (Elems v) ~ a , HVector v , HVector w , Elems w ~ NewElems (Peano n) (Elems v) b ) => proxy n -- ^ Type level index -> Lens v w a b {-# INLINE elementCh #-} elementCh _ f v = inspect v $ lensChF (Proxy @(Peano n)) f construct -- | Lookup field from product by its type. Product must contain one -- and only one field of type @a@ -- -- >>> tyLookup ('c',"str") :: Char -- 'c' -- -- >>> tyLookup ('c',"str") :: Int -- ... -- • Cannot find type: -- Int -- • In the expression: tyLookup ('c', "str") :: Int -- In an equation for ‘it’: it = tyLookup ('c', "str") :: Int -- -- >>> tyLookup ('c','c') :: Char -- ... -- • Duplicate type found: -- Char -- • In the expression: tyLookup ('c', 'c') :: Char -- In an equation for ‘it’: it = tyLookup ('c', 'c') :: Char tyLookup :: (HVector v, TyLookup a (Elems v)) => v -> a tyLookup = C.tyLookup . C.cvec {-# INLINE tyLookup #-} -- | Analog of 'tyLookup' for @HVectorF@ tyLookupF :: (HVectorF v, TyLookup a (ElemsF v)) => v f -> f a tyLookupF = C.tyLookupF . C.cvecF {-# INLINE tyLookupF #-} ---------------------------------------------------------------- -- Folds over vector ---------------------------------------------------------------- -- | Right fold over heterogeneous vector -- -- >>> foldr (Proxy @Show) (\x str -> show x : str) [] (12,'c') -- ["12","'c'"] foldr :: (HVector v, ArityC c (Elems v)) => Proxy c -> (forall a. c a => a -> b -> b) -> b -> v -> b {-# INLINE foldr #-} foldr c f b0 = C.foldrF c (\(Identity a) b -> f a b) b0 . C.cvec -- | Left fold over heterogeneous vector foldl :: (HVector v, ArityC c (Elems v)) => Proxy c -> (forall a. c a => b -> a -> b) -> b -> v -> b {-# INLINE foldl #-} foldl c f b0 = C.foldlF c (\b (Identity a) -> f b a) b0 . C.cvec -- | Monoidal fold over heterogeneuous vector -- -- >>> foldMap (Proxy @Show) show (12,'c',"str") -- "12'c'\"str\"" foldMap :: (HVector v, ArityC c (Elems v), Monoid m) => Proxy c -> (forall a. c a => a -> m) -> v -> m {-# INLINE foldMap #-} foldMap c f = C.foldMapF c (\(Identity a) -> f a) . C.cvec -- | Right fold over heterogeneous vector foldrF :: (HVectorF v, ArityC c (ElemsF v)) => Proxy c -> (forall a. c a => f a -> b -> b) -> b -> v f -> b {-# INLINE foldrF #-} foldrF c f b0 = C.foldrF c f b0 . C.cvecF -- | Left fold over heterogeneous vector foldlF :: (HVectorF v, ArityC c (ElemsF v)) => Proxy c -> (forall a. c a => b -> f a -> b) -> b -> v f -> b {-# INLINE foldlF #-} foldlF c f b0 = C.foldlF c f b0 . C.cvecF -- | Monoidal fold over heterogeneous vector -- -- >>> foldMapF (Proxy @Show) show (mk2F (Just 1) Nothing :: HVecF '[Int,Char] Maybe) -- "Just 1Nothing" foldMapF :: (HVectorF v, ArityC c (ElemsF v), Monoid m) => Proxy c -> (forall a. c a => f a -> m) -> v f -> m {-# INLINE foldMapF #-} foldMapF c f = C.foldMapF c f . C.cvecF -- | Right fold over heterogeneous vector foldrNatF :: (HVectorF v) => (forall a. f a -> b -> b) -> b -> v f -> b {-# INLINE foldrNatF #-} foldrNatF f b0 = C.foldrNatF f b0 . C.cvecF -- | Left fold over heterogeneous vector foldlNatF :: (HVectorF v) => (forall a. b -> f a -> b) -> b -> v f -> b {-# INLINE foldlNatF #-} foldlNatF f b0 = C.foldlNatF f b0 . C.cvecF -- | Monoidal fold over heterogeneous vector -- -- >>> foldMapNatF (Sum . getConst) (mk2F (Const 1) (Const 2) :: HVecF '[Char,String] (Const Int)) -- Sum {getSum = 3} foldMapNatF :: (HVectorF v, Monoid m) => (forall a. f a -> m) -> v f -> m {-# INLINE foldMapNatF #-} foldMapNatF f = C.foldMapNatF f . C.cvecF -- | Apply monadic action to every element in the vector mapM_ :: (HVector v, ArityC c (Elems v), Applicative f) => Proxy c -> (forall a. c a => a -> f ()) -> v -> f () {-# INLINE mapM_ #-} mapM_ c f = foldl c (\m a -> m *> f a) (pure ()) -- | Unfold vector. unfoldr :: (HVector v, ArityC c (Elems v)) => Proxy c -> (forall a. c a => b -> (a,b)) -> b -> v {-# INLINE unfoldr #-} unfoldr c f = C.vector . C.unfoldrF c (\b -> let (a,b') = f b in (Identity a, b')) -- | Unfold vector. unfoldrF :: (HVectorF v, ArityC c (ElemsF v)) => Proxy c -> (forall a. c a => b -> (f a,b)) -> b -> v f {-# INLINE unfoldrF #-} unfoldrF c f = C.vectorF . C.unfoldrF c f ---------------------------------------------------------------- -- Constructors ---------------------------------------------------------------- -- $construction -- -- Functions below allow to construct products up to 5 elements. Here -- are example for product types from base: -- -- >>> mk0 :: () -- () -- -- >>> mk3 12 'x' "xyz" :: (Int,Char,String) -- (12,'x',"xyz") -- -- >>> mk2 0 1 :: Complex Double -- 0.0 :+ 1.0 mk0 :: forall v. (HVector v, Elems v ~ '[]) => v mk0 = coerce (construct :: Fun '[] v) {-# INLINE mk0 #-} mk1 :: forall v a. (HVector v, Elems v ~ '[a]) => a -> v mk1 = coerce (construct :: Fun '[a] v) {-# INLINE mk1 #-} mk2 :: forall v a b. (HVector v, Elems v ~ '[a,b]) => a -> b -> v mk2 = coerce (construct :: Fun '[a,b] v) {-# INLINE mk2 #-} mk3 :: forall v a b c. (HVector v, Elems v ~ '[a,b,c]) => a -> b -> c -> v mk3 = coerce (construct :: Fun '[a,b,c] v) {-# INLINE mk3 #-} mk4 :: forall v a b c d. (HVector v, Elems v ~ '[a,b,c,d]) => a -> b -> c -> d -> v mk4 = coerce (construct :: Fun '[a,b,c,d] v) {-# INLINE mk4 #-} mk5 :: forall v a b c d e. (HVector v, Elems v ~ '[a,b,c,d,e]) => a -> b -> c -> d -> e -> v mk5 = coerce (construct :: Fun '[a,b,c,d,e] v) {-# INLINE mk5 #-} -- $construction_F -- -- Construction function for parametrized products are fully -- analogous to plain products: -- -- >>>mk2F (Identity 'c') (Identity 1) :: HVecF '[Char, Int] Identity -- [Identity 'c',Identity 1] -- -- >>>mk2F (Nothing) (Just 1) :: HVecF '[Char, Int] Maybe -- [Nothing,Just 1] mk0F :: forall f v. (HVectorF v, ElemsF v ~ '[]) => v f mk0F = coerce (constructF :: TFun f '[] (v f)) {-# INLINE mk0F #-} mk1F :: forall f v a. (HVectorF v, ElemsF v ~ '[a]) => f a -> v f mk1F = coerce (constructF :: TFun f '[a] (v f)) {-# INLINE mk1F #-} mk2F :: forall f v a b. (HVectorF v, ElemsF v ~ '[a,b]) => f a -> f b -> v f mk2F = coerce (constructF :: TFun f '[a,b] (v f)) {-# INLINE mk2F #-} mk3F :: forall f v a b c. (HVectorF v, ElemsF v ~ '[a,b,c]) => f a -> f b -> f c -> v f mk3F = coerce (constructF :: TFun f '[a,b,c] (v f)) {-# INLINE mk3F #-} mk4F :: forall f v a b c d. (HVectorF v, ElemsF v ~ '[a,b,c,d]) => f a -> f b -> f c -> f d -> v f mk4F = coerce (constructF :: TFun f '[a,b,c,d] (v f)) {-# INLINE mk4F #-} mk5F :: forall f v a b c d e. (HVectorF v, ElemsF v ~ '[a,b,c,d,e]) => f a -> f b -> f c -> f d -> f e -> v f mk5F = coerce (constructF :: TFun f '[a,b,c,d,e] (v f)) {-# INLINE mk5F #-} ---------------------------------------------------------------- -- Collective operations ---------------------------------------------------------------- -- | Apply function to every value of parametrized product. -- -- >>> map (Proxy @Num) (Identity . fromMaybe 0) (mk2F (Just 12) Nothing :: HVecF '[Double, Int] Maybe) -- [Identity 12.0,Identity 0] map :: (HVectorF v, ArityC c (ElemsF v)) => Proxy c -> (forall a. c a => f a -> g a) -> v f -> v g {-# INLINE map #-} map cls f = C.vectorF . C.map cls f . C.cvecF -- | Apply natural transformation to every element of the tuple. -- -- >>> mapNat (Just . runIdentity) (mk2F (pure 'c') (pure 1) :: HVecF '[Char, Int] Identity) -- [Just 'c',Just 1] mapNat :: (HVectorF v) => (forall a. f a -> g a) -> v f -> v g {-# INLINE mapNat #-} mapNat f = C.vectorF . C.mapNat f . C.cvecF -- | Sequence effects for every element in the vector -- -- >>> sequence (mk2F [1,2] "ab" :: HVecF '[Int,Char] []) :: [(Int,Char)] -- [(1,'a'),(1,'b'),(2,'a'),(2,'b')] sequence :: ( Applicative f, HVectorF v, HVector w, ElemsF v ~ Elems w ) => v f -> f w {-# INLINE sequence #-} sequence = fmap C.vector . C.sequenceF . C.mapNat (Compose . fmap Identity) . C.cvecF -- | Sequence effects for every element in the vector sequence_ :: (Applicative f, HVectorF v) => v f -> f () {-# INLINE sequence_ #-} sequence_ = foldlNatF (\m a -> m <* a) (pure ()) -- | Sequence effects for every element in the vector sequenceF :: ( Applicative f, HVectorF v) => v (f `Compose` g) -> f (v g) {-# INLINE sequenceF #-} sequenceF v = C.vectorF <$> C.sequenceF (C.cvecF v) -- | Wrap every value in the vector into type constructor. wrap :: ( HVector v, HVectorF w, Elems v ~ ElemsF w ) => (forall a. a -> f a) -> v -> w f {-# INLINE wrap #-} wrap f = C.vectorF . C.mapNat (f . runIdentity) . C.cvec -- | Unwrap every value in the vector from the type constructor. unwrap :: ( HVectorF v, HVector w, ElemsF v ~ Elems w ) => (forall a. f a -> a) -> v f -> w {-# INLINE unwrap #-} unwrap f = C.vector . C.mapNat (Identity . f) . C.cvecF -- | Analog of /distribute/ from /Distributive/ type class. distribute :: ( Functor f, HVector v, HVectorF w, Elems v ~ ElemsF w ) => f v -> w f {-# INLINE distribute #-} distribute = C.vectorF . mapNat (fmap runIdentity . getCompose) . C.distributeF . fmap C.cvec -- | Analog of /distribute/ from /Distributive/ type class. distributeF :: ( Functor f, HVectorF v) => f (v g) -> v (f `Compose` g) {-# INLINE distributeF #-} distributeF = C.vectorF . C.distributeF . fmap C.cvecF ---------------------------------------------------------------- -- Type class based ops ---------------------------------------------------------------- -- | Replicate polymorphic value n times. Concrete instance for every -- element is determined by their respective types. -- -- >>> replicate (Proxy :: Proxy Monoid) mempty :: ((),String) -- ((),"") -- -- Or a bit contrived example which illustrate what how to call -- function that require multiple type class constraints: -- -- >>> replicate (Proxy @(Monoid :&&: Num)) (mempty * 10) :: (Product Int, Sum Int) -- (Product {getProduct = 10},Sum {getSum = 0}) replicate :: (HVector v, ArityC c (Elems v)) => Proxy c -> (forall x. c x => x) -> v {-# INLINE replicate #-} replicate c x = C.vector $ C.replicateF c (Identity x) -- | Replicate monadic action n times. Example below is a bit awkward does convey what's -- -- >>> :{ -- Prelude.mapM_ print -- (replicateM (Proxy @(Monoid :&&: Num)) [mempty+1, mempty * 10] :: [(Product Int, Sum Int)]) -- :} -- (Product {getProduct = 2},Sum {getSum = 1}) -- (Product {getProduct = 2},Sum {getSum = 0}) -- (Product {getProduct = 10},Sum {getSum = 1}) -- (Product {getProduct = 10},Sum {getSum = 0}) replicateM :: (HVector v, Applicative f, ArityC c (Elems v)) => Proxy c -> (forall a. c a => f a) -> f v {-# INLINE replicateM #-} replicateM c x = fmap C.vector $ C.sequenceF $ C.replicateF c (Compose $ fmap Identity x) -- | Replicate value @f a@ which is valid for every type a n times. -- -- >>> replicateNatF Nothing :: HVecF '[Char,Int] Maybe -- [Nothing,Nothing] replicateNatF :: (HVectorF v, Arity (ElemsF v)) => (forall a. f a) -> v f {-# INLINE replicateNatF #-} replicateNatF x = C.vectorF $ C.replicateNatF x -- | Replicate polymorphic value n times: -- -- >>> replicateF (Proxy @Num) (Just 0) :: HVecF '[Double,Int] Maybe -- [Just 0.0,Just 0] replicateF :: (HVectorF v, ArityC c (ElemsF v)) => Proxy c -> (forall a. c a => f a) -> v f {-# INLINE replicateF #-} replicateF c x = C.vectorF $ C.replicateF c x ---------------------------------------------------------------- -- Zipping of vectors ---------------------------------------------------------------- -- | Zip two heterogeneous vectors -- -- >>> zipWith (Proxy @Num) (+) (0, 1.2) (1, 10) :: (Int,Double) -- (1,11.2) zipWith :: (HVector v, ArityC c (Elems v)) => Proxy c -> (forall a. c a => a -> a -> a) -> v -> v -> v {-# INLINE zipWith #-} zipWith c f v u = C.vector $ C.zipWithF c (\(Identity a) (Identity b) -> Identity (f a b)) (C.cvec v) (C.cvec u) -- | Zip two heterogeneous vectors zipWithF :: (HVectorF v, ArityC c (ElemsF v)) => Proxy c -> (forall a. c a => f a -> g a -> h a) -> v f -> v g -> v h {-# INLINE zipWithF #-} zipWithF c f v u = C.vectorF $ C.zipWithF c f (C.cvecF v) (C.cvecF u) -- | Zip two heterogeneous vectors zipWithNatF :: (HVectorF v) => (forall a. f a -> g a -> h a) -> v f -> v g -> v h {-# INLINE zipWithNatF #-} zipWithNatF f v u = C.vectorF $ C.zipWithNatF f (C.cvecF v) (C.cvecF u) -- | Zip two heterogeneous vectors and immediately fold resulting -- value. -- -- >>> zipFold (Proxy @Show) (\a b -> show (a,b)) ((),'c',10) ((),'D',1) -- "((),())('c','D')(10,1)" zipFold :: (HVector v, ArityC c (Elems v), Monoid m) => Proxy c -> (forall a. c a => a -> a -> m) -> v -> v -> m {-# INLINE zipFold #-} zipFold c f v u = C.zipFoldF c (\(Identity a) (Identity b) -> f a b) (C.cvec v) (C.cvec u) zipFoldF :: (HVectorF v, ArityC c (ElemsF v), Monoid m) => Proxy c -> (forall a. c a => f a -> f a -> m) -> v f -> v f -> m {-# INLINE zipFoldF #-} zipFoldF c f v u = C.zipFoldF c f (C.cvecF v) (C.cvecF u) -- | Convert heterogeneous vector to homogeneous monomorphize :: ( HVector v , Peano n ~ Len (Elems v) , ArityC c (Elems v)) => Proxy c -> (forall a. c a => a -> x) -> v -> F.ContVec n x {-# INLINE monomorphize #-} monomorphize c f = C.monomorphizeF c (f . runIdentity) . C.cvec -- | Convert heterogeneous vector to homogeneous monomorphizeF :: ( HVectorF v , Peano n ~ Len (ElemsF v) , ArityC c (ElemsF v) ) => Proxy c -> (forall a. c a => f a -> x) -> v f -> F.ContVec n x {-# INLINE monomorphizeF #-} monomorphizeF c f = C.monomorphizeF c f . C.cvecF -- | Generic equality for heterogeneous vectors -- -- >>> data A = A Int Char deriving Generic -- >>> instance HVector A -- >>> eq (A 1 'c') (A 2 'c') -- False eq :: (HVector v, ArityC Eq (Elems v)) => v -> v -> Bool eq v u = getAll $ zipFold (Proxy :: Proxy Eq) (\x y -> All (x == y)) v u {-# INLINE eq #-} -- | Generic comparison for heterogeneous vectors. It works same way -- as Ord instance for tuples. -- -- >>> data A = A Int Char deriving Generic -- >>> instance HVector A -- >>> compare (A 1 'c') (A 2 'c') -- LT compare :: (HVector v, ArityC Ord (Elems v)) => v -> v -> Ordering compare = zipFold (Proxy :: Proxy Ord) Prelude.compare {-# INLINE compare #-} -- | Reduce vector to normal form rnf :: (HVector v, ArityC NF.NFData (Elems v)) => v -> () rnf = foldl (Proxy :: Proxy NF.NFData) (\r a -> NF.rnf a `seq` r) () {-# INLINE rnf #-} ---------------------------------------------------------------- -- Doctest ---------------------------------------------------------------- -- $setup -- -- >>> :set -XDeriveGeneric -- >>> :set -XTypeApplications -- >>> :set -XTypeOperators -- >>> :set -XDataKinds -- >>> import Prelude (Int,Double,String,Char,IO,(++),Maybe(..)) -- >>> import Prelude (Show(..),Read(..),read,Num(..),Monoid(..)) -- >>> import Prelude (print) -- >>> import Control.Applicative (Const(..)) -- >>> import Data.Complex (Complex(..)) -- >>> import Data.Monoid (Sum(..),Product(..)) -- >>> import Data.Maybe (fromMaybe) -- >>> import Data.Vector.HFixed.HVec (HVec,HVecF) -- >>> import GHC.Generics (Generic)