36
36
-----------------------------------------------------------------------------
37
37
38
38
module Control.Parallel.Strategies (
39
- -- * The strategy type
39
+ -- * The strategy types
40
40
Strategy
41
+ , Strategy'
41
42
42
43
-- * Application of strategies
43
44
, using -- :: a -> Strategy a -> a
@@ -279,26 +280,27 @@ instance Monad Eval where
279
280
-- value. This idiom is expressed by the 'using' function.
280
281
--
281
282
type Strategy a = a -> Eval a
283
+ type Strategy' a b = a -> Eval b
282
284
283
285
-- | Evaluate a value using the given 'Strategy'.
284
286
--
285
287
-- > x `using` s = runEval (s x)
286
288
--
287
- using :: a -> Strategy a -> a
289
+ using :: a -> Strategy' a b -> b
288
290
x `using` strat = runEval (strat x)
289
291
290
292
-- | evaluate a value using the given 'Strategy'. This is simply
291
293
-- 'using' with the arguments reversed.
292
294
--
293
- withStrategy :: Strategy a -> a -> a
295
+ withStrategy :: Strategy' a b -> a -> b
294
296
withStrategy = flip using
295
297
296
298
-- | Compose two strategies sequentially.
297
299
-- This is the analogue to function composition on strategies.
298
300
--
299
301
-- > strat2 `dot` strat1 == strat2 . withStrategy strat1
300
302
--
301
- dot :: Strategy a -> Strategy a -> Strategy a
303
+ dot :: Strategy' b c -> Strategy' a b -> Strategy' a c
302
304
strat2 `dot` strat1 = strat2 . runEval . strat1
303
305
304
306
-- Proof of strat2 `dot` strat1 == strat2 . withStrategy strat1
@@ -407,7 +409,7 @@ rpar x = case (par# x) of { _ -> Done x }
407
409
-- spark that does no evaluation).
408
410
--
409
411
--
410
- rparWith :: Strategy a -> Strategy a
412
+ rparWith :: Strategy' a b -> Strategy' a b
411
413
#if __GLASGOW_HASKELL__ >= 702
412
414
rparWith s = rpar `dot` s
413
415
#else
@@ -419,12 +421,12 @@ rparWith s a = do l <- rpar (s a); return (case l of Done x -> x)
419
421
420
422
-- | Evaluate the elements of a traversable data structure
421
423
-- according to the given strategy.
422
- evalTraversable :: Traversable t => Strategy a -> Strategy (t a )
424
+ evalTraversable :: Traversable t => Strategy' a b -> Strategy' (t a ) ( t b )
423
425
evalTraversable = traverse
424
426
{-# INLINE evalTraversable #-}
425
427
426
428
-- | Like 'evalTraversable' but evaluates all elements in parallel.
427
- parTraversable :: Traversable t => Strategy a -> Strategy (t a )
429
+ parTraversable :: Traversable t => Strategy' a b -> Strategy' (t a ) ( t b )
428
430
parTraversable strat = evalTraversable (rparWith strat)
429
431
{-# INLINE parTraversable #-}
430
432
@@ -433,7 +435,7 @@ parTraversable strat = evalTraversable (rparWith strat)
433
435
434
436
-- | Evaluate each element of a list according to the given strategy.
435
437
-- Equivalent to 'evalTraversable' at the list type.
436
- evalList :: Strategy a -> Strategy [a ]
438
+ evalList :: Strategy' a b -> Strategy' [a ] [ b ]
437
439
evalList = evalTraversable
438
440
-- Alternative explicitly recursive definition:
439
441
-- evalList strat [] = return []
@@ -443,23 +445,23 @@ evalList = evalTraversable
443
445
444
446
-- | Evaluate each element of a list in parallel according to given strategy.
445
447
-- Equivalent to 'parTraversable' at the list type.
446
- parList :: Strategy a -> Strategy [a ]
448
+ parList :: Strategy' a b -> Strategy' [a ] [ b ]
447
449
parList = parTraversable
448
450
-- Alternative definition via evalList:
449
451
-- parList strat = evalList (rparWith strat)
450
452
451
453
-- | @'evaListSplitAt' n stratPref stratSuff@ evaluates the prefix
452
454
-- (of length @n@) of a list according to @stratPref@ and its the suffix
453
455
-- according to @stratSuff@.
454
- evalListSplitAt :: Int -> Strategy [a ] -> Strategy [a ] -> Strategy [a ]
456
+ evalListSplitAt :: Int -> Strategy' [a ] [ b ] -> Strategy' [a ] [ b ] -> Strategy' [a ] [ b ]
455
457
evalListSplitAt n stratPref stratSuff xs
456
458
= let (ys,zs) = splitAt n xs in
457
459
stratPref ys >>= \ ys' ->
458
460
stratSuff zs >>= \ zs' ->
459
461
return (ys' ++ zs')
460
462
461
463
-- | Like 'evalListSplitAt' but evaluates both sublists in parallel.
462
- parListSplitAt :: Int -> Strategy [a ] -> Strategy [a ] -> Strategy [a ]
464
+ parListSplitAt :: Int -> Strategy' [a ] [ b ] -> Strategy' [a ] [ b ] -> Strategy' [a ] [ b ]
463
465
parListSplitAt n stratPref stratSuff = evalListSplitAt n (rparWith stratPref) (rparWith stratSuff)
464
466
465
467
-- | Evaluate the first n elements of a list according to the given strategy.
@@ -491,7 +493,7 @@ parListNth n strat = evalListNth n (rparWith strat)
491
493
-- If the chunk size is 1 or less, 'parListChunk' is equivalent to
492
494
-- 'parList'
493
495
--
494
- parListChunk :: Int -> Strategy a -> Strategy [a ]
496
+ parListChunk :: Int -> Strategy' a b -> Strategy' [a ] [ b ]
495
497
parListChunk n strat xs
496
498
| n <= 1 = parList strat xs
497
499
| otherwise = concat `fmap` parList (evalList strat) (chunk n xs)
@@ -506,9 +508,9 @@ chunk n xs = as : chunk n bs where (as,bs) = splitAt n xs
506
508
-- | A combination of 'parList' and 'map', encapsulating a common pattern:
507
509
--
508
510
-- > parMap strat f = withStrategy (parList strat) . map f
509
- --
510
- parMap :: Strategy b -> (a -> b ) -> [a ] -> [b ]
511
- parMap strat f = ( `using` parList strat) . map f
511
+ -- > parMap strat f = withStrategy (parList (strat . f))
512
+ parMap :: Strategy' b c -> (a -> b ) -> [a ] -> [c ]
513
+ parMap strat f = withStrategy ( parList ( strat . f))
512
514
513
515
-- --------------------------------------------------------------------------
514
516
-- Strategies for lazy lists
@@ -535,7 +537,7 @@ evalBufferWHNF n0 xs0 = return (ret xs0 (start n0 xs0))
535
537
--
536
538
-- > evalBuffer n r0 == evalBuffer n rseq
537
539
--
538
- evalBuffer :: Int -> Strategy a -> Strategy [a ]
540
+ evalBuffer :: Int -> Strategy' a b -> Strategy' [a ] [ b ]
539
541
evalBuffer n strat = evalBufferWHNF n . map (withStrategy strat)
540
542
541
543
-- Like evalBufferWHNF but sparks the list elements when pushing them
@@ -555,7 +557,7 @@ parBufferWHNF n0 xs0 = return (ret xs0 (start n0 xs0))
555
557
556
558
-- | Like 'evalBuffer' but evaluates the list elements in parallel when
557
559
-- pushing them into the buffer.
558
- parBuffer :: Int -> Strategy a -> Strategy [a ]
560
+ parBuffer :: Int -> Strategy' a b -> Strategy' [a ] [ b ]
559
561
parBuffer n strat = parBufferWHNF n . map (withStrategy strat)
560
562
-- Alternative definition via evalBuffer (may compromise firing of RULES):
561
563
-- parBuffer n strat = evalBuffer n (rparWith strat)
@@ -573,109 +575,151 @@ parBuffer n strat = parBufferWHNF n . map (withStrategy strat)
573
575
-- --------------------------------------------------------------------------
574
576
-- Strategies for tuples
575
577
576
- evalTuple2 :: Strategy a -> Strategy b -> Strategy (a ,b )
578
+ evalTuple2 :: Strategy' a a' -> Strategy' b b' -> Strategy' (a ,b ) ( a' , b' )
577
579
evalTuple2 strat1 strat2 (x1,x2) =
578
580
pure (,) <*> strat1 x1 <*> strat2 x2
579
581
580
- evalTuple3 :: Strategy a -> Strategy b -> Strategy c -> Strategy (a ,b ,c )
582
+ evalTuple3 :: Strategy' a a'
583
+ -> Strategy' b b'
584
+ -> Strategy' c c'
585
+ -> Strategy' (a ,b ,c ) (a' ,b' ,c' )
581
586
evalTuple3 strat1 strat2 strat3 (x1,x2,x3) =
582
587
pure (,,) <*> strat1 x1 <*> strat2 x2 <*> strat3 x3
583
588
584
- evalTuple4 :: Strategy a -> Strategy b -> Strategy c -> Strategy d -> Strategy (a ,b ,c ,d )
589
+ evalTuple4 :: Strategy' a a'
590
+ -> Strategy' b b'
591
+ -> Strategy' c c'
592
+ -> Strategy' d d'
593
+ -> Strategy' (a ,b ,c ,d ) (a' ,b' ,c' ,d' )
585
594
evalTuple4 strat1 strat2 strat3 strat4 (x1,x2,x3,x4) =
586
595
pure (,,,) <*> strat1 x1 <*> strat2 x2 <*> strat3 x3 <*> strat4 x4
587
596
588
- evalTuple5 :: Strategy a -> Strategy b -> Strategy c -> Strategy d -> Strategy e -> Strategy (a ,b ,c ,d ,e )
597
+ evalTuple5 :: Strategy' a a'
598
+ -> Strategy' b b'
599
+ -> Strategy' c c'
600
+ -> Strategy' d d'
601
+ -> Strategy' e e'
602
+ -> Strategy' (a ,b ,c ,d ,e ) (a' ,b' ,c' ,d' ,e' )
589
603
evalTuple5 strat1 strat2 strat3 strat4 strat5 (x1,x2,x3,x4,x5) =
590
604
pure (,,,,) <*> strat1 x1 <*> strat2 x2 <*> strat3 x3 <*> strat4 x4 <*> strat5 x5
591
605
592
- evalTuple6 :: Strategy a -> Strategy b -> Strategy c -> Strategy d -> Strategy e -> Strategy f -> Strategy (a ,b ,c ,d ,e ,f )
606
+ evalTuple6 :: Strategy' a a'
607
+ -> Strategy' b b'
608
+ -> Strategy' c c'
609
+ -> Strategy' d d'
610
+ -> Strategy' e e'
611
+ -> Strategy' f f'
612
+ -> Strategy' (a ,b ,c ,d ,e ,f ) (a' ,b' ,c' ,d' ,e' ,f' )
593
613
evalTuple6 strat1 strat2 strat3 strat4 strat5 strat6 (x1,x2,x3,x4,x5,x6) =
594
614
pure (,,,,,) <*> strat1 x1 <*> strat2 x2 <*> strat3 x3 <*> strat4 x4 <*> strat5 x5 <*> strat6 x6
595
615
596
- evalTuple7 :: Strategy a -> Strategy b -> Strategy c -> Strategy d -> Strategy e -> Strategy f -> Strategy g -> Strategy (a ,b ,c ,d ,e ,f ,g )
616
+ evalTuple7 :: Strategy' a a'
617
+ -> Strategy' b b'
618
+ -> Strategy' c c'
619
+ -> Strategy' d d'
620
+ -> Strategy' e e'
621
+ -> Strategy' f f'
622
+ -> Strategy' g g'
623
+ -> Strategy' (a ,b ,c ,d ,e ,f ,g ) (a' ,b' ,c' ,d' ,e' ,f' ,g' )
597
624
evalTuple7 strat1 strat2 strat3 strat4 strat5 strat6 strat7 (x1,x2,x3,x4,x5,x6,x7) =
598
625
pure (,,,,,,) <*> strat1 x1 <*> strat2 x2 <*> strat3 x3 <*> strat4 x4 <*> strat5 x5 <*> strat6 x6 <*> strat7 x7
599
626
600
- evalTuple8 :: Strategy a -> Strategy b -> Strategy c -> Strategy d -> Strategy e -> Strategy f -> Strategy g -> Strategy h -> Strategy (a ,b ,c ,d ,e ,f ,g ,h )
627
+ evalTuple8 :: Strategy' a a'
628
+ -> Strategy' b b'
629
+ -> Strategy' c c'
630
+ -> Strategy' d d'
631
+ -> Strategy' e e'
632
+ -> Strategy' f f'
633
+ -> Strategy' g g'
634
+ -> Strategy' h h'
635
+ -> Strategy' (a ,b ,c ,d ,e ,f ,g ,h ) (a' ,b' ,c' ,d' ,e' ,f' ,g' ,h' )
601
636
evalTuple8 strat1 strat2 strat3 strat4 strat5 strat6 strat7 strat8 (x1,x2,x3,x4,x5,x6,x7,x8) =
602
637
pure (,,,,,,,) <*> strat1 x1 <*> strat2 x2 <*> strat3 x3 <*> strat4 x4 <*> strat5 x5 <*> strat6 x6 <*> strat7 x7 <*> strat8 x8
603
638
604
- evalTuple9 :: Strategy a -> Strategy b -> Strategy c -> Strategy d -> Strategy e -> Strategy f -> Strategy g -> Strategy h -> Strategy i -> Strategy (a ,b ,c ,d ,e ,f ,g ,h ,i )
639
+ evalTuple9 :: Strategy' a a'
640
+ -> Strategy' b b'
641
+ -> Strategy' c c'
642
+ -> Strategy' d d'
643
+ -> Strategy' e e'
644
+ -> Strategy' f f'
645
+ -> Strategy' g g'
646
+ -> Strategy' h h'
647
+ -> Strategy' i i'
648
+ -> Strategy' (a ,b ,c ,d ,e ,f ,g ,h ,i ) (a' ,b' ,c' ,d' ,e' ,f' ,g' ,h' ,i' )
605
649
evalTuple9 strat1 strat2 strat3 strat4 strat5 strat6 strat7 strat8 strat9 (x1,x2,x3,x4,x5,x6,x7,x8,x9) =
606
650
pure (,,,,,,,,) <*> strat1 x1 <*> strat2 x2 <*> strat3 x3 <*> strat4 x4 <*> strat5 x5 <*> strat6 x6 <*> strat7 x7 <*> strat8 x8 <*> strat9 x9
607
651
608
- parTuple2 :: Strategy a -> Strategy b -> Strategy (a ,b )
652
+ parTuple2 :: Strategy' a a' -> Strategy' b b' -> Strategy' (a ,b ) ( a' , b' )
609
653
parTuple2 strat1 strat2 =
610
654
evalTuple2 (rparWith strat1) (rparWith strat2)
611
655
612
- parTuple3 :: Strategy a -> Strategy b -> Strategy c -> Strategy (a ,b ,c )
656
+ parTuple3 :: Strategy' a a' -> Strategy' b b' -> Strategy' c c' -> Strategy' (a ,b ,c ) ( a' , b' , c' )
613
657
parTuple3 strat1 strat2 strat3 =
614
658
evalTuple3 (rparWith strat1) (rparWith strat2) (rparWith strat3)
615
659
616
- parTuple4 :: Strategy a -> Strategy b -> Strategy c -> Strategy d -> Strategy (a ,b ,c ,d )
660
+ parTuple4 :: Strategy' a a' -> Strategy' b b' -> Strategy' c c' -> Strategy' d d' -> Strategy' (a ,b ,c ,d ) ( a' , b' , c' , d' )
617
661
parTuple4 strat1 strat2 strat3 strat4 =
618
662
evalTuple4 (rparWith strat1) (rparWith strat2) (rparWith strat3) (rparWith strat4)
619
663
620
- parTuple5 :: Strategy a -> Strategy b -> Strategy c -> Strategy d -> Strategy e -> Strategy (a ,b ,c ,d ,e )
664
+ parTuple5 :: Strategy' a a' -> Strategy' b b' -> Strategy' c c' -> Strategy' d d' -> Strategy' e e' -> Strategy' (a ,b ,c ,d ,e ) ( a' , b' , c' , d' , e' )
621
665
parTuple5 strat1 strat2 strat3 strat4 strat5 =
622
666
evalTuple5 (rparWith strat1) (rparWith strat2) (rparWith strat3) (rparWith strat4) (rparWith strat5)
623
667
624
- parTuple6 :: Strategy a -> Strategy b -> Strategy c -> Strategy d -> Strategy e -> Strategy f -> Strategy (a ,b ,c ,d ,e ,f )
668
+ parTuple6 :: Strategy' a a' -> Strategy' b b' -> Strategy' c c' -> Strategy' d d' -> Strategy' e e' -> Strategy' f f' -> Strategy' (a ,b ,c ,d ,e ,f ) ( a' , b' , c' , d' , e' , f' )
625
669
parTuple6 strat1 strat2 strat3 strat4 strat5 strat6 =
626
670
evalTuple6 (rparWith strat1) (rparWith strat2) (rparWith strat3) (rparWith strat4) (rparWith strat5) (rparWith strat6)
627
671
628
- parTuple7 :: Strategy a -> Strategy b -> Strategy c -> Strategy d -> Strategy e -> Strategy f -> Strategy g -> Strategy (a ,b ,c ,d ,e ,f ,g )
672
+ parTuple7 :: Strategy' a a' -> Strategy' b b' -> Strategy' c c' -> Strategy' d d' -> Strategy' e e' -> Strategy' f f' -> Strategy' g g' -> Strategy' (a ,b ,c ,d ,e ,f ,g ) ( a' , b' , c' , d' , e' , f' , g' )
629
673
parTuple7 strat1 strat2 strat3 strat4 strat5 strat6 strat7 =
630
674
evalTuple7 (rparWith strat1) (rparWith strat2) (rparWith strat3) (rparWith strat4) (rparWith strat5) (rparWith strat6) (rparWith strat7)
631
675
632
- parTuple8 :: Strategy a -> Strategy b -> Strategy c -> Strategy d -> Strategy e -> Strategy f -> Strategy g -> Strategy h -> Strategy (a ,b ,c ,d ,e ,f ,g ,h )
676
+ parTuple8 :: Strategy' a a' -> Strategy' b b' -> Strategy' c c' -> Strategy' d d' -> Strategy' e e' -> Strategy' f f' -> Strategy' g g' -> Strategy' h h' -> Strategy' (a ,b ,c ,d ,e ,f ,g ,h ) ( a' , b' , c' , d' , e' , f' , g' , h' )
633
677
parTuple8 strat1 strat2 strat3 strat4 strat5 strat6 strat7 strat8 =
634
678
evalTuple8 (rparWith strat1) (rparWith strat2) (rparWith strat3) (rparWith strat4) (rparWith strat5) (rparWith strat6) (rparWith strat7) (rparWith strat8)
635
679
636
- parTuple9 :: Strategy a -> Strategy b -> Strategy c -> Strategy d -> Strategy e -> Strategy f -> Strategy g -> Strategy h -> Strategy i -> Strategy (a ,b ,c ,d ,e ,f ,g ,h ,i )
680
+ parTuple9 :: Strategy' a a' -> Strategy' b b' -> Strategy' c c' -> Strategy' d d' -> Strategy' e e' -> Strategy' f f' -> Strategy' g g' -> Strategy' h h' -> Strategy' i i' -> Strategy' (a ,b ,c ,d ,e ,f ,g ,h ,i ) ( a' , b' , c' , d' , e' , f' , g' , h' , i' )
637
681
parTuple9 strat1 strat2 strat3 strat4 strat5 strat6 strat7 strat8 strat9 =
638
682
evalTuple9 (rparWith strat1) (rparWith strat2) (rparWith strat3) (rparWith strat4) (rparWith strat5) (rparWith strat6) (rparWith strat7) (rparWith strat8) (rparWith strat9)
639
683
640
684
-- --------------------------------------------------------------------------
641
685
-- Strategic function application
642
686
643
687
{-
644
- These are very handy when writing pipeline parallelism asa sequence of
688
+ These are very handy when writing pipeline parallelism as a sequence of
645
689
@$@, @$|@ and @$||@'s. There is no need of naming intermediate values
646
690
in this case. The separation of algorithm from strategy is achieved by
647
691
allowing strategies only as second arguments to @$|@ and @$||@.
648
692
-}
649
693
650
694
-- | Sequential function application. The argument is evaluated using
651
695
-- the given strategy before it is given to the function.
652
- ($|) :: (a -> b ) -> Strategy a -> a -> b
696
+ ($|) :: (b -> c ) -> Strategy' a b -> a -> c
653
697
f $| s = \ x -> let z = x `using` s in z `pseq` f z
654
698
655
699
-- | Parallel function application. The argument is evaluated using
656
700
-- the given strategy, in parallel with the function application.
657
- ($||) :: (a -> b ) -> Strategy a -> a -> b
701
+ ($||) :: (b -> c ) -> Strategy' a b -> a -> c
658
702
f $|| s = \ x -> let z = x `using` s in z `par` f z
659
703
660
704
-- | Sequential function composition. The result of
661
705
-- the second function is evaluated using the given strategy,
662
706
-- and then given to the first function.
663
- (.|) :: (b -> c ) -> Strategy b -> (a -> b ) -> (a -> c )
707
+ (.|) :: (c -> d ) -> Strategy' b c -> (a -> b ) -> (a -> d )
664
708
(.|) f s g = \ x -> let z = g x `using` s in
665
709
z `pseq` f z
666
710
667
711
-- | Parallel function composition. The result of the second
668
712
-- function is evaluated using the given strategy,
669
713
-- in parallel with the application of the first function.
670
- (.||) :: (b -> c ) -> Strategy b -> (a -> b ) -> (a -> c )
714
+ (.||) :: (c -> d ) -> Strategy' b c -> (a -> b ) -> (a -> d )
671
715
(.||) f s g = \ x -> let z = g x `using` s in
672
716
z `par` f z
673
717
674
718
-- | Sequential inverse function composition,
675
719
-- for those who read their programs from left to right.
676
720
-- The result of the first function is evaluated using the
677
721
-- given strategy, and then given to the second function.
678
- (-|) :: (a -> b ) -> Strategy b -> (b -> c ) -> (a -> c )
722
+ (-|) :: (a -> b ) -> Strategy' b c -> (c -> d ) -> (a -> d )
679
723
(-|) f s g = \ x -> let z = f x `using` s in
680
724
z `pseq` g z
681
725
@@ -684,15 +728,15 @@ f $|| s = \ x -> let z = x `using` s in z `par` f z
684
728
-- The result of the first function is evaluated using the
685
729
-- given strategy, in parallel with the application of the
686
730
-- second function.
687
- (-||) :: (a -> b ) -> Strategy b -> (b -> c ) -> (a -> c )
731
+ (-||) :: (a -> b ) -> Strategy' b c -> (c -> d ) -> (a -> d )
688
732
(-||) f s g = \ x -> let z = f x `using` s in
689
733
z `par` g z
690
734
691
735
-- -----------------------------------------------------------------------------
692
736
-- Old/deprecated stuff
693
737
694
738
{-# DEPRECATED Done "The Strategy type is now a -> Eval a, not a -> Done" #-}
695
- -- | DEPRECCATED : replaced by the 'Eval' monad
739
+ -- | DEPRECATED : replaced by the 'Eval' monad
696
740
type Done = ()
697
741
698
742
{-# DEPRECATED demanding "Use pseq or $| instead" #-}
0 commit comments