-
Notifications
You must be signed in to change notification settings - Fork 132
Expand file tree
/
Copy pathAccelerate.hs
More file actions
698 lines (615 loc) · 24.5 KB
/
Accelerate.hs
File metadata and controls
698 lines (615 loc) · 24.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
-- |
-- Module : Data.Array.Accelerate
-- Description : The Accelerate standard prelude
-- Copyright : [2008..2020] The Accelerate Team
-- License : BSD3
--
-- Maintainer : Trevor L. McDonell <trevor.mcdonell@gmail.com>
-- Stability : experimental
-- Portability : non-portable (GHC extensions)
--
-- @Data.Array.Accelerate@ defines an embedded language of array computations
-- for high-performance computing in Haskell. Computations on multi-dimensional,
-- regular arrays are expressed in the form of parameterised collective
-- operations such as maps, reductions, and permutations. These computations are
-- online compiled and can be executed on a range of architectures.
--
-- [/Abstract interface:/]
--
-- The types representing array computations are only exported abstractly;
-- client code can generate array computations and submit them for execution,
-- but it cannot inspect these computations. This is to allow for more
-- flexibility for future extensions of this library.
--
-- [/Stratified language:/]
--
-- Accelerate distinguishes the types of collective operations 'Acc' from the
-- type of scalar operations 'Exp' to achieve a stratified language. Collective
-- operations comprise many scalar computations that are executed in parallel,
-- but scalar computations /can not/ contain collective operations. This
-- separation excludes /nested, irregular/ data-parallelism statically; instead,
-- Accelerate is limited to /flat data-parallelism/ involving only regular,
-- multi-dimensional arrays.
--
-- [/Optimisations:/]
--
-- Accelerate uses a number of scalar and array optimisations, including
-- /array fusion/, in order to improve the performance of programs. Fusing
-- a program entails combining successive traversals (loops) over an array into
-- a single traversal, which reduces memory traffic and eliminates intermediate
-- arrays.
--
-- [/Code execution:/]
--
-- Several backends are available which can be used to evaluate accelerate
-- programs:
--
-- * "Data.Array.Accelerate.Interpreter": simple interpreter in Haskell as a
-- reference implementation defining the semantics of the Accelerate language
--
-- * <http://hackage.haskell.org/package/accelerate-llvm-native accelerate-llvm-native>:
-- implementation supporting parallel execution on multicore CPUs (e.g. x86).
--
-- * <http://hackage.haskell.org/package/accelerate-llvm-ptx accelerate-llvm-ptx>:
-- implementation supporting parallel execution on CUDA-capable NVIDIA GPUs.
--
-- [/Examples:/]
--
-- * A short tutorial-style example for generating a <https://en.wikipedia.org/wiki/Mandelbrot_set Mandelbrot set>:
-- http://www.acceleratehs.org/examples/mandelbrot.html
--
-- * The <http://hackage.haskell.org/package/accelerate-examples accelerate-examples>
-- package demonstrates a range of computational kernels and several complete
-- applications:
--
-- - Implementation of the <https://en.wikipedia.org/wiki/Canny_edge_detector canny edge detector>
-- - Interactive <https://en.wikipedia.org/wiki/Mandelbrot_set Mandelbrot set> generator
-- - <https://en.wikipedia.org/wiki/N-body N-body simulation> of gravitational attraction between large bodies
-- - Implementation of the <https://en.wikipedia.org/wiki/Pagerank PageRank> algorithm
-- - A simple, real-time, interactive <https://en.wikipedia.org/wiki/Ray_tracing ray tracer>.
-- - A particle based simulation of stable fluid flows
-- - A cellular automaton simulation
-- - A "password recovery" tool, for dictionary attacks on MD5 hashes.
--
-- <<http://i.imgur.com/5Tbsp1j.jpg accelerate-mandelbrot>>
-- <<http://i.imgur.com/7ohhKm9.jpg accelerate-ray>>
--
-- * <http://hackage.haskell.org/package/lulesh-accelerate lulesh-accelerate>
-- is an implementation of the Livermore Unstructured Lagrangian Explicit
-- Shock Hydrodynamics (LULESH) application. LULESH is representative of
-- typical hydrodynamics codes, although simplified and hard-coded to solve
-- the Sedov blast problem on an unstructured hexahedron mesh.
--
-- - For more information on LULESH: <https://codesign.llnl.gov/lulesh.php>.
--
-- <<https://i.imgur.com/bIkODKd.jpg>>
--
-- [/Starting a new project:/]
--
-- Accelerate and its associated packages are available on both Hackage and
-- Stackage. A project template is available to help create a new projects using
-- the <https://docs.haskellstack.org/en/stable/README/ stack> build tool. To
-- create a new project using the template:
--
-- > stack new PROJECT_NAME https://github.com/AccelerateHS/accelerate/raw/stable/accelerate.hsfiles
--
-- [/Additional components:/]
--
-- * <https://hackage.haskell.org/package/accelerate-io accelerate-io>: Fast
-- conversion between Accelerate arrays and other formats (e.g. Repa, Vector).
--
-- * <https://hackage.haskell.org/package/accelerate-fft accelerate-fft>: Fast
-- Fourier transform, with FFI bindings to optimised implementations.
--
-- * <https://hackage.haskell.org/package/accelerate-blas accelerate-blas>: BLAS
-- and LAPACK operations, with FFI bindings to optimised implementations.
--
-- * <https://hackage.haskell.org/package/accelerate-bignum accelerate-bignum>:
-- Fixed-width large integer arithmetic.
--
-- * <https://hackage.haskell.org/package/containers-accelerate containers-accelerate>:
-- Container types for use with Accelerate.
--
-- * <https://hackage.haskell.org/package/hashable-accelerate hashable-accelerate>:
-- Class for types which can be converted to a value.
--
-- * <https://hackage.haskell.org/package/colour-accelerate colour-accelerate>:
-- Colour representations in Accelerate (RGB, sRGB, HSV, and HSL).
--
-- * <https://hackage.haskell.org/package/gloss-accelerate gloss-accelerate>:
-- Generate <https://hackage.haskell.org/package/gloss gloss> pictures from
-- Accelerate.
--
-- * <https://hackage.haskell.org/package/gloss-raster-accelerate gloss-raster-accelerate>:
-- Parallel rendering of raster images and animations.
--
-- * <https://hackage.haskell.org/package/lens-accelerate lens-accelerate>:
-- <https://hackage.haskell.org/package/lens Lens> operators for Accelerate
-- types.
--
-- * <https://hackage.haskell.org/package/linear-accelerate linear-accelerate>:
-- <https://hackage.haskell.org/package/linear Linear> vector space types for
-- Accelerate.
--
-- * <https://hackage.haskell.org/package/mwc-random-accelerate mwc-random-accelerate>:
-- Generate Accelerate arrays filled with high-quality pseudorandom numbers.
--
-- [/Contact:/]
--
-- * Mailing list for both use and development discussion:
--
-- * <mailto:accelerate-haskell@googlegroups.com>
-- * http://groups.google.com/group/accelerate-haskell
--
-- * Bug reports: https://github.com/AccelerateHS/accelerate/issues
--
-- * Maintainer: Trevor L. McDonell: <mailto:trevor.mcdonell@gmail.com>
--
-- [/Tip:/]
--
-- Accelerate tends to stress GHC's garbage collector, so it helps to increase
-- the default GC allocation sizes. This can be done when running an executable
-- by specifying RTS options on the command line, for example:
--
-- > ./foo +RTS -A64M -n2M -RTS
--
-- You can make these settings the default by adding the following @ghc-options@
-- to your @.cabal@ file or similar:
--
-- > ghc-options: -with-rtsopts=-n2M -with-rtsopts=-A64M
--
-- To specify RTS options you will also need to compile your program with @-rtsopts@.
--
module Data.Array.Accelerate (
-- * The /Accelerate/ Array Language
-- ** Embedded array computations
Acc,
-- *** Arrays
Array, Arrays, Scalar, Vector, Matrix, Segments,
-- *** Array elements
Elt,
-- *** Array shapes & indices
-- $shapes_and_indices
--
Z(..), (:.)(..),
DIM0, DIM1, DIM2, DIM3, DIM4, DIM5, DIM6, DIM7, DIM8, DIM9,
Shape, Slice(..), All(..), Any(..),
-- Split(..), Divide(..), Division(..),
-- ** Array access
-- *** Element indexing
(!), (!!), the,
-- *** Shape information
null, length, shape, size, shapeSize,
-- ** Construction
-- *** Introduction
use, unit,
-- *** Initialisation
generate, fill,
-- *** Enumeration
enumFromN, enumFromStepN,
-- *** Concatenation
(++), concatOn,
-- *** Expansion
expand,
-- ** Composition
-- *** Flow control
(?|), acond, awhile,
IfThenElse(..),
-- *** Controlling execution
(>->),
compute,
-- ** Element-wise operations
-- *** Indexing
indexed,
-- *** Mapping
map, imap,
-- *** Zipping
zipWith, zipWith3, zipWith4, zipWith5, zipWith6, zipWith7, zipWith8, zipWith9,
izipWith, izipWith3, izipWith4, izipWith5, izipWith6, izipWith7, izipWith8, izipWith9,
zip, zip3, zip4, zip5, zip6, zip7, zip8, zip9,
-- *** Unzipping
unzip, unzip3, unzip4, unzip5, unzip6, unzip7, unzip8, unzip9,
-- ** Modifying Arrays
-- *** Shape manipulation
reshape, flatten,
-- *** Replication
replicate,
-- *** Extracting sub-arrays
slice,
init, tail, take, drop, slit,
initOn, tailOn, takeOn, dropOn, slitOn,
-- *** Permutations
-- **** Forward permutation (scatter)
permute,
scatter,
-- **** Backward permutation (gather)
backpermute,
gather,
-- **** Specialised permutations
reverse, transpose,
reverseOn, transposeOn,
-- *** Filtering
filter, compact,
-- ** Folding
fold, fold1, foldAll, fold1All,
-- *** Segmented reductions
foldSeg, fold1Seg,
foldSeg', fold1Seg',
-- *** Specialised reductions
all, any, and, or, sum, product, minimum, maximum,
-- ** Scans (prefix sums)
scanl, scanl1, scanl', scanr, scanr1, scanr',
prescanl, postscanl, prescanr, postscanr,
-- *** Segmented scans
scanlSeg, scanl1Seg, scanl'Seg, prescanlSeg, postscanlSeg,
scanrSeg, scanr1Seg, scanr'Seg, prescanrSeg, postscanrSeg,
-- ** Stencils
stencil, stencil2,
-- *** Stencil specification
Stencil, Boundary,
clamp, mirror, wrap, function,
-- *** Common stencil patterns
Unary(..),
Stencil1, Stencil3, Stencil5, Stencil7, Stencil9,
Stencil1x1, Stencil1x3, Stencil1x5,
Stencil3x1, Stencil3x3, Stencil3x5,
Stencil5x1, Stencil5x3, Stencil5x5,
Stencil3x3x3, Stencil3x5x3, Stencil3x3x5, Stencil3x5x5,
Stencil5x3x3, Stencil5x5x3, Stencil5x3x5, Stencil5x5x5,
-- -- ** Sequence operations
-- collect,
-- -- ** Sequence producers
-- streamIn, toSeq, generateSeq,
-- -- ** Sequence transducers
-- mapSeq, zipWithSeq, scanSeq,
-- -- ** Sequence consumers
-- foldSeq, foldSeqFlatten, fromSeq, fromSeqElems, fromSeqShapes,
-- toSeqInner, toSeqOuter2, toSeqOuter3,
-- ---------------------------------------------------------------------------
-- * The /Accelerate/ Expression Language
-- ** Scalar data types
Exp,
-- ** SIMD vectors
Vec, VecElt,
-- ** Type classes
-- *** Basic type classes
Eq(..),
Ord(..), Ordering(..), pattern LT_, pattern EQ_, pattern GT_,
Enum, succ, pred,
Bounded, minBound, maxBound,
-- Functor(..), (<$>), ($>), void,
-- Monad(..),
-- *** Numeric type classes
Num, (+), (-), (*), negate, abs, signum, fromInteger,
Integral, quot, rem, div, mod, quotRem, divMod,
Rational(..),
Fractional, (/), recip, fromRational,
Floating, pi, sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh, exp, sqrt, log, (**), logBase,
RealFrac(..), div', mod', divMod',
RealFloat(..),
-- *** Numeric conversion classes
FromIntegral(..),
ToFloating(..),
-- ** Lifting and Unlifting
-- $lifting_and_unlifting
--
Lift(..), Unlift(..),
lift1, lift2, lift3,
ilift1, ilift2, ilift3,
-- ** Pattern synonyms
-- $pattern_synonyms
--
pattern Pattern,
pattern T1,
pattern T2, pattern T3, pattern T4, pattern T5, pattern T6,
pattern T7, pattern T8, pattern T9, pattern T10, pattern T11,
pattern T12, pattern T13, pattern T14, pattern T15, pattern T16,
pattern Z_, pattern Ix, pattern (::.), pattern All_, pattern Any_,
pattern I0, pattern I1, pattern I2, pattern I3, pattern I4,
pattern I5, pattern I6, pattern I7, pattern I8, pattern I9,
pattern Vec2, pattern V2,
pattern Vec3, pattern V3,
pattern Vec4, pattern V4,
pattern Vec8, pattern V8,
pattern Vec16, pattern V16,
mkPattern, mkPatterns,
-- ** Scalar operations
-- *** Introduction
constant,
-- *** Tuples
fst, afst, snd, asnd, curry, uncurry,
-- *** Flow control
(?), match, cond, while, iterate,
-- *** Scalar reduction
sfoldl,
-- *** Logical operations
(&&), (||), not,
-- *** Numeric operations
subtract, even, odd, gcd, lcm, (^), (^^),
-- *** Shape manipulation
index0, index1, unindex1, index2, unindex2, index3, unindex3,
indexHead, indexTail,
toIndex, fromIndex,
intersect,
-- *** Conversions
ord, chr, boolToInt, bitcast,
-- ---------------------------------------------------------------------------
-- * Foreign Function Interface (FFI)
foreignAcc,
foreignExp,
-- ---------------------------------------------------------------------------
-- * Plain arrays
-- ** Operations
arrayRank, arrayShape, arraySize, arrayReshape,
indexArray, linearIndexArray,
-- ** Getting data in
-- $getting_data_in
-- *** Function
fromFunction,
fromFunctionM,
-- *** Lists
fromList, toList,
-- ---------------------------------------------------------------------------
-- * Useful re-exports
(.), ($), (&), flip, error, undefined, const, otherwise,
Show, Generic, HasCallStack,
fromString, -- -XOverloadedStrings
fromListN, -- -XOverloadedLists
-- ---------------------------------------------------------------------------
-- Types
Int, Int8, Int16, Int32, Int64,
Word, Word8, Word16, Word32, Word64,
Half(..), Float, Double,
Bool(..), pattern True_, pattern False_,
Maybe(..), pattern Nothing_, pattern Just_,
Either(..), pattern Left_, pattern Right_,
Char,
CFloat, CDouble,
CShort, CUShort, CInt, CUInt, CLong, CULong, CLLong, CULLong,
CChar, CSChar, CUChar,
) where
import Data.Array.Accelerate.Classes.Bounded
import Data.Array.Accelerate.Classes.Enum
import Data.Array.Accelerate.Classes.Eq
import Data.Array.Accelerate.Classes.Floating
import Data.Array.Accelerate.Classes.Fractional
import Data.Array.Accelerate.Classes.FromIntegral
import Data.Array.Accelerate.Classes.Integral
import Data.Array.Accelerate.Classes.Num
import Data.Array.Accelerate.Classes.Ord
import Data.Array.Accelerate.Classes.Rational
import Data.Array.Accelerate.Classes.RealFloat
import Data.Array.Accelerate.Classes.RealFrac
import Data.Array.Accelerate.Classes.ToFloating
import Data.Array.Accelerate.Data.Either
import Data.Array.Accelerate.Data.Maybe
import Data.Array.Accelerate.Language
import Data.Array.Accelerate.Pattern
import Data.Array.Accelerate.Pattern.TH
import Data.Array.Accelerate.Prelude
import Data.Array.Accelerate.Pretty () -- show instances
import Data.Array.Accelerate.Smart
import Data.Array.Accelerate.Sugar.Array ( Array, Arrays, Scalar, Vector, Matrix, Segments, fromFunction, fromFunctionM, toList, fromList )
import Data.Array.Accelerate.Sugar.Elt
import Data.Array.Accelerate.Sugar.Shape hiding ( size, toIndex, fromIndex, intersect )
import Data.Array.Accelerate.Sugar.Vec
import Data.Array.Accelerate.Type
import Data.Primitive.Vec
import qualified Data.Array.Accelerate.Sugar.Array as S
import qualified Data.Array.Accelerate.Sugar.Shape as S
import Data.Function ( (&) )
import Prelude ( (.), ($), Char, Show, flip, undefined, error, const, otherwise )
import GHC.Exts ( fromListN, fromString )
import GHC.Generics ( Generic )
import GHC.Stack
-- $setup
-- >>> :seti -XTypeOperators
-- >>> import Data.Array.Accelerate.Interpreter
-- >>> :{
-- let runExp :: Elt e => Exp e -> e
-- runExp e = indexArray (run (unit e)) Z
-- :}
-- Renamings
-- ---------
--
-- FIXME: these all need to go into a separate module for separate importing!
-- rename as '(!)' is already used by the EDSL for indexing
-- | Array indexing in plain Haskell code.
--
{-# INLINE indexArray #-}
indexArray :: (Shape sh, Elt e) => Array sh e -> sh -> e
indexArray = (S.!)
-- | Linear array indexing in plain Haskell code.
--
{-# INLINE linearIndexArray #-}
linearIndexArray :: Elt e => Array sh e -> Int -> e
linearIndexArray = (S.!!)
-- | Rank of an array (as a plain Haskell value)
--
{-# INLINE arrayRank #-}
arrayRank :: forall sh e. Shape sh => Array sh e -> Int
arrayRank _ = S.rank @sh
-- | Shape of an array (as a plain Haskell value)
--
{-# INLINE arrayShape #-}
arrayShape :: Shape sh => Array sh e -> sh
arrayShape = S.shape
-- rename as 'shape' is already used by the EDSL to query an array's shape
-- | Total number of elements in an array (as a plain Haskell value)
--
{-# INLINE arraySize #-}
arraySize :: Shape sh => Array sh e -> Int
arraySize = S.size . S.shape
-- | Change the shape of an array without altering its contents. The 'arraySize'
-- of the source and result arrays must be identical.
--
{-# INLINE arrayReshape #-}
arrayReshape :: (Shape sh, Shape sh') => sh -> Array sh' e -> Array sh e
arrayReshape = S.reshape
-- Named documentation chunks
-- --------------------------
-- $shapes_and_indices
--
-- Operations in Accelerate take the form of collective operations over arrays
-- of the type @'Array' sh e@. Much like the
-- <https://hackage.haskell.org/package/repa repa> library, arrays in Accelerate
-- are parameterised by a type /sh/ which determines the dimensionality of the
-- array and the type of each index, as well as the type of each element of the
-- array /e/.
--
-- Shape types, and multidimensional array indices, are built like lists
-- (technically; a heterogeneous snoc-list) using 'Z' and (':.'):
--
-- > data Z = Z
-- > data tail :. head = tail :. head
--
-- Here, the constructor 'Z' corresponds to a shape with zero dimension (or
-- a 'Scalar' array, with one element) and is used to mark the end of the list.
-- The constructor (':.') adds additional dimensions to the shape on the
-- /right/. For example:
--
-- > Z :. Int
--
-- is the type of the shape of a one-dimensional array ('Vector') indexed by an
-- 'Int', while:
--
-- > Z :. Int :. Int
--
-- is the type of the shape of a two-dimensional array (a matrix) indexed by an
-- 'Int' in each dimension.
--
-- This style is used to construct both the /type/ and /value/ of the shape. For
-- example, to define the shape of a vector of ten elements:
--
-- > sh :: Z :. Int
-- > sh = Z :. 10
--
-- Note that the right-most index is the /innermost/ dimension. This is the
-- fastest-varying index, and corresponds to the elements of the array which are
-- adjacent in memory.
--
-- $lifting_and_unlifting
--
-- A value of type 'Int' is a plain Haskell value (unlifted), whereas an @Exp
-- Int@ is a /lifted/ value, that is, an integer lifted into the domain of
-- embedded expressions (an abstract syntax tree in disguise). Both 'Acc' and
-- 'Exp' are /surface types/ into which values may be lifted. Lifting plain
-- array and scalar surface types is equivalent to 'use' and 'constant'
-- respectively.
--
-- In general an @Exp Int@ cannot be unlifted into an 'Int', because the actual
-- number will not be available until a later stage of execution (e.g. during
-- GPU execution, when 'run' is called). Similarly an @Acc array@ can not be
-- unlifted to a vanilla 'array'; you should instead 'run' the expression with
-- a specific backend to evaluate it.
--
-- Lifting and unlifting are also used to pack and unpack an expression into and
-- out of constructors such as tuples, respectively. Those expressions, at
-- runtime, will become tuple dereferences. For example:
--
-- >>> let sh = constant (Z :. 4 :. 10) :: Exp DIM2
-- >>> let Z :. x :. y = unlift sh :: Z :. Exp Int :. Exp Int
-- >>> let t = lift (x,y) :: Exp (Int, Int)
--
-- >>> let xs = use $ fromList (Z:.10) [0..] :: Acc (Vector Int)
-- >>> let ys = use $ fromList (Z:.3:.4) [0..] :: Acc (Matrix Int)
-- >>> let r = (xs,ys) :: (Acc (Vector Int), Acc (Matrix Int))
-- >>> let r' = lift r :: Acc (Vector Int, Matrix Int)
--
-- [/Note:/]
--
-- Use of 'lift' and 'unlift' is probably the most common source of type errors
-- when using Accelerate. GHC is not very good at determining the type the
-- [un]lifted expression should have, so it is often necessary to add an
-- explicit type signature.
--
-- For example, in the following GHC will complain that it can not determine the
-- type of 'y', even though we might expect that to be obvious (or for it to not
-- care):
--
-- > fst :: (Elt a, Elt b) => Exp (a,b) -> Exp a
-- > fst t = let (x,y) = unlift t in x
--
-- The fix is to instead add an explicit type signature. Note that this requires
-- the @ScopedTypeVariables@ extension and to bring the type variables @a@ and
-- @b@ into scope with @forall@:
--
-- > fst :: forall a b. (Elt a, Elt b) => Exp (a,b) -> Exp a
-- > fst t = let (x,y) = unlift t :: (Exp a, Exp b)
-- > in x
--
-- For an alternative, see section <#pattern_synonyms Pattern synonyms>.
--
-- $pattern_synonyms
-- #pattern_synonyms#
--
-- Pattern synonyms can be used as an alternative to 'lift' and 'unlift' for
-- constructing and accessing data types isomorphic to simple product (tuple)
-- types.
--
-- In contrast to 'lift' and 'unlift' however, pattern synonyms do /not/ require
-- these data types to be fully polymorphic.
--
-- For example, let's say we have regular Haskell data type representing a point
-- in two-dimensional space:
--
-- > data Point = Point_ Float Float
-- > deriving (Generic, Elt)
--
-- Here we derive instance an instance of the 'Elt' class (via 'Generic'),
-- so that this data type can be used within scalar Accelerate expressions
--
-- In order to access the individual fields of the data constructor from within
-- an Accelerate expression, we define the following pattern synonym:
--
-- > pattern Point :: Exp Float -> Exp Float -> Exp Point
-- > pattern Point x y = Pattern (x,y)
--
-- Notice how we named the constructor of our original datatype with a trailing
-- underscore, so that we can use the undecorated name for the pattern synonym;
-- these must have unique names.
--
-- In essence, the 'Pattern' pattern is really telling GHC how to treat our @Point@
-- type as a regular pair for use in Accelerate code. The pattern can then be
-- used on both the left and right hand side of an expression:
--
-- > addPoint :: Exp Point -> Exp Point -> Exp Point
-- > addPoint (Point x1 y1) (Point x2 y2) = Point (x1+x2) (y1+y2)
--
-- Similarly, we can define pattern synonyms for values in 'Acc'. We can also
-- use record syntax to generate field accessors, if we desire:
--
-- > data SparseVector a = SparseVector_ (Vector Int) (Vector a)
-- > deriving (Generic, Arrays)
-- >
-- > pattern SparseVector :: Elt a => Acc (Vector Int) -> Acc (Vector a) -> Acc (SparseVector a)
-- > pattern SparseVector { indices, values } = Pattern (indices, values)
--
-- For convenience, we have defined several pattern synonyms for regular tuples,
-- 'T2' (for pairs), 'T3' (for triples), and so on up to 'T16'. These are
-- occasionally more convenient to use than 'lift' and 'unlift' together with
-- the regular tuple syntax.
--
-- @since 1.3.0.0
--
-- $getting_data_in
-- #getting_data_in#
--
-- We often need to generate or read data into an 'Array' so that it can be used
-- in Accelerate. The base @accelerate@ library includes basic conversions
-- routines, but additional functionality is contained in external
-- libraries, for example:
--
-- * <https://hackage.haskell.org/package/accelerate-io accelerate-io>: For copying data directly from raw 'Foreign.Ptr.Ptr's
-- * <https://hackage.haskell.org/package/accelerate-io-array accelerate-io-array>: immutable arrays
-- * <https://hackage.haskell.org/package/accelerate-io-bmp accelerate-io-bmp>: uncompressed BMP image files
-- * <https://hackage.haskell.org/package/accelerate-io-bytestring accelerate-io-bytestring>: compact, immutable binary data
-- * <https://hackage.haskell.org/package/accelerate-io-cereal accelerate-io-cereal>: binary serialisation of arrays using <https://hackage.haskell.org/package/cereal cereal>
-- * <https://hackage.haskell.org/package/accelerate-io-JuicyPixels accelerate-io-JuicyPixels>: images in various pixel formats
-- * <https://hackage.haskell.org/package/accelerate-io-repa accelerate-io-repa>: another Haskell library for high-performance parallel arrays
-- * <https://hackage.haskell.org/package/accelerate-io-serialise accelerate-io-serialise>: binary serialisation of arrays using <https://hackage.haskell.org/package/serialise serialise>
-- * <https://hackage.haskell.org/package/accelerate-io-vector accelerate-io-vector>: efficient boxed and unboxed one-dimensional arrays
--