packages feed

gambler 0.3.0.0 → 0.4.0.0

raw patch · 23 files changed

+211/−127 lines, 23 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Fold.Shortcut: [extractDead] :: ShortcutFold a b -> x -> b
- Fold.Shortcut: [extractLive] :: ShortcutFold a b -> y -> b
- Fold.Shortcut.Type: [extractDead] :: ShortcutFold a b -> x -> b
- Fold.Shortcut.Type: [extractLive] :: ShortcutFold a b -> y -> b
- Fold.ShortcutNonempty: [extractDead] :: ShortcutNonemptyFold a b -> x -> b
- Fold.ShortcutNonempty: [extractLive] :: ShortcutNonemptyFold a b -> y -> b
- Fold.ShortcutNonempty.Type: [extractDead] :: ShortcutNonemptyFold a b -> x -> b
- Fold.ShortcutNonempty.Type: [extractLive] :: ShortcutNonemptyFold a b -> y -> b
+ Fold.Shortcut: [extract] :: ShortcutFold a b -> Vitality x y -> b
+ Fold.Shortcut: duplicate :: ShortcutFold a b -> ShortcutFold a (ShortcutFold a b)
+ Fold.Shortcut.Type: [extract] :: ShortcutFold a b -> Vitality x y -> b
+ Fold.Shortcut.Utilities: duplicate :: ShortcutFold a b -> ShortcutFold a (ShortcutFold a b)
+ Fold.ShortcutNonempty: [extract] :: ShortcutNonemptyFold a b -> Vitality x y -> b
+ Fold.ShortcutNonempty: duplicate :: ShortcutNonemptyFold a b -> ShortcutNonemptyFold a (ShortcutFold a b)
+ Fold.ShortcutNonempty.Type: [extract] :: ShortcutNonemptyFold a b -> Vitality x y -> b
+ Fold.ShortcutNonempty.Utilities: duplicate :: ShortcutNonemptyFold a b -> ShortcutNonemptyFold a (ShortcutFold a b)
- Fold: ShortcutFold :: Vitality x y -> (y -> a -> Vitality x y) -> (x -> b) -> (y -> b) -> ShortcutFold a b
+ Fold: ShortcutFold :: Vitality x y -> (y -> a -> Vitality x y) -> (Vitality x y -> b) -> ShortcutFold a b
- Fold: ShortcutNonemptyFold :: (a -> Vitality x y) -> (y -> a -> Vitality x y) -> (x -> b) -> (y -> b) -> ShortcutNonemptyFold a b
+ Fold: ShortcutNonemptyFold :: (a -> Vitality x y) -> (y -> a -> Vitality x y) -> (Vitality x y -> b) -> ShortcutNonemptyFold a b
- Fold.Shortcut: ShortcutFold :: Vitality x y -> (y -> a -> Vitality x y) -> (x -> b) -> (y -> b) -> ShortcutFold a b
+ Fold.Shortcut: ShortcutFold :: Vitality x y -> (y -> a -> Vitality x y) -> (Vitality x y -> b) -> ShortcutFold a b
- Fold.Shortcut.Type: ShortcutFold :: Vitality x y -> (y -> a -> Vitality x y) -> (x -> b) -> (y -> b) -> ShortcutFold a b
+ Fold.Shortcut.Type: ShortcutFold :: Vitality x y -> (y -> a -> Vitality x y) -> (Vitality x y -> b) -> ShortcutFold a b
- Fold.ShortcutNonempty: ShortcutNonemptyFold :: (a -> Vitality x y) -> (y -> a -> Vitality x y) -> (x -> b) -> (y -> b) -> ShortcutNonemptyFold a b
+ Fold.ShortcutNonempty: ShortcutNonemptyFold :: (a -> Vitality x y) -> (y -> a -> Vitality x y) -> (Vitality x y -> b) -> ShortcutNonemptyFold a b
- Fold.ShortcutNonempty.Type: ShortcutNonemptyFold :: (a -> Vitality x y) -> (y -> a -> Vitality x y) -> (x -> b) -> (y -> b) -> ShortcutNonemptyFold a b
+ Fold.ShortcutNonempty.Type: ShortcutNonemptyFold :: (a -> Vitality x y) -> (y -> a -> Vitality x y) -> (Vitality x y -> b) -> ShortcutNonemptyFold a b

Files

changelog.md view
@@ -1,3 +1,47 @@+## 0.4.0.0 (2023-03-08)++Changed `ShortcutFold` from++```haskell+data ShortcutFold a b = forall x y. ShortcutFold+    { initial     :: Vitality x y+    , step        :: y -> a -> Vitality x y+    , extractDead :: x -> b+    , extractLive :: y -> b }+```++to++```haskell+data ShortcutFold a b = forall x y. ShortcutFold+    { initial :: Vitality x y+    , step    :: y -> a -> Vitality x y+    , extract :: Vitality x y -> b }+```++Changed `ShortcutNonemptyFold` from++```haskell+data ShortcutNonemptyFold a b = forall x y. ShortcutNonemptyFold+    { initial     :: a -> Vitality x y+    , step        :: y -> a -> Vitality x y+    , extractDead :: x -> b+    , extractLive :: y -> b }+```++to++```haskell+data ShortcutNonemptyFold a b = forall x y. ShortcutNonemptyFold+    { initial :: a -> Vitality x y+    , step    :: y -> a -> Vitality x y+    , extract :: Vitality x y -> b }+```++Added `Fold.Shortcut.duplicate` and `Fold.ShortcutNonempty.duplicate`.++(The type changes make the `duplicate` functions possible.)+ ## 0.3.0.0 (2023-03-07)  In the `Fold.ShortcutNonempty` module, the type of `list` and
gambler.cabal view
@@ -1,7 +1,7 @@ cabal-version: 3.0  name: gambler-version: 0.3.0.0+version: 0.4.0.0  category: Streaming synopsis: Composable, streaming, and efficient left folds
readme.md view
@@ -176,11 +176,9 @@  ```haskell data ShortcutFold a b = forall x y. ShortcutFold-    { initial     :: Vitality x y-    , step        :: y -> a -> Vitality x y-    , extractDead :: x -> b-    , extractLive :: y -> b-    }+    { initial :: Vitality x y+    , step    :: y -> a -> Vitality x y+    , extract :: Vitality x y -> b } ```  ```haskell@@ -220,11 +218,9 @@  ```haskell data ShortcutNonemptyFold a b = forall x y. ShortcutNonemptyFold-    { initial     :: a -> Vitality x y-    , step        :: y -> a -> Vitality x y-    , extractDead :: x -> b-    , extractLive :: y -> b-    }+    { initial :: a -> Vitality x y+    , step    :: y -> a -> Vitality x y+    , extract :: Vitality x y -> b } ```  Like `NonemptyFold`, the only thing we've changed here is to add an `a`
source/Fold/Nonempty/Conversion.hs view
@@ -30,11 +30,9 @@  shortcutNonemptyFold :: ShortcutNonemptyFold a b -> NonemptyFold a b shortcutNonemptyFold ShortcutNonemptyFold{ ShortcutNonempty.step,-        ShortcutNonempty.initial, ShortcutNonempty.extractDead, ShortcutNonempty.extractLive } =+        ShortcutNonempty.initial, ShortcutNonempty.extract } =     NonemptyFold       { initial = initial       , step = \s -> case s of { Dead _ -> \_ -> s; Alive _ x -> step x }-      , extract = \s -> case s of-            Dead x -> extractDead x-            Alive _ x -> extractLive x+      , extract = extract       }
source/Fold/Pure/Conversion.hs view
@@ -44,25 +44,21 @@  shortcutFold :: ShortcutFold a b -> Fold a b shortcutFold ShortcutFold{-        Shortcut.initial, Shortcut.step, Shortcut.extractLive, Shortcut.extractDead } =+        Shortcut.initial, Shortcut.step, Shortcut.extract } =     Fold       { initial = initial       , step = \s -> case s of { Dead _ -> \_ -> s; Alive _ x -> step x }-      , extract = \s -> case s of-            Dead    x -> extractDead x-            Alive _ x -> extractLive x+      , extract       }  shortcutNonemptyFold :: ShortcutNonemptyFold a b -> Fold a (Maybe b) shortcutNonemptyFold ShortcutNonemptyFold{ ShortcutNonempty.initial,-        ShortcutNonempty.step, ShortcutNonempty.extractLive, ShortcutNonempty.extractDead } =+        ShortcutNonempty.step, ShortcutNonempty.extract } =     Fold       { initial = Strict.Nothing       , step = \xm a -> case xm of             Strict.Nothing -> Strict.Just (initial a)             Strict.Just (Alive _ x) -> Strict.Just (step x a)             Strict.Just (Dead    _) -> xm-      , extract = \xm -> Strict.lazy xm <&> \s -> case s of-            Dead    x -> extractDead x-            Alive _ x -> extractLive x+      , extract = \xm -> Strict.lazy xm <&> extract       }
source/Fold/Shortcut.hs view
@@ -17,7 +17,7 @@      {- * Conversion -} fold, effectfulFold, nonemptyFold, shortcutNonemptyFold, -    {- * Utilities -} demotivate,+    {- * Utilities -} demotivate, duplicate,   )   where 
source/Fold/Shortcut/Conversion.hs view
@@ -22,8 +22,7 @@     ShortcutFold       { initial = Alive Ambivalent initial       , step = \x a -> Alive Ambivalent (step x a)-      , extractDead = absurd-      , extractLive = extract+      , extract = \v -> case v of { Alive _ x -> extract x; Dead x -> absurd x }       }  effectfulFold :: EffectfulFold Identity a b -> ShortcutFold a b@@ -34,12 +33,13 @@  shortcutNonemptyFold :: ShortcutNonemptyFold a b -> ShortcutFold a (Maybe b) shortcutNonemptyFold ShortcutNonemptyFold{ ShortcutNonempty.initial,-        ShortcutNonempty.step, ShortcutNonempty.extractDead, ShortcutNonempty.extractLive } =+        ShortcutNonempty.step, ShortcutNonempty.extract } =     ShortcutFold       { initial = Alive Tenacious Strict.Nothing       , step = \xm a -> Strict.Just <$> case xm of             Strict.Nothing -> initial a             Strict.Just x -> step x a-      , extractDead = \x -> Just (extractDead x)-      , extractLive = \xm -> extractLive <$> Strict.lazy xm+      , extract = \v -> case v of+          Dead x -> Just (extract (Dead x))+          Alive w xm -> (\x -> extract (Alive w x)) <$> Strict.lazy xm       }
source/Fold/Shortcut/Examples/Interesting.hs view
@@ -10,14 +10,15 @@ import Fold.Shortcut.Type  import Control.Applicative (liftA2)-import Data.Bool (Bool (False, True))+import Data.Bool (Bool) import Data.Eq (Eq, (/=), (==)) import Data.Functor (($>), (<&>)) import Data.Maybe (Maybe (Just, Nothing))-import Numeric.Natural (Natural)-import Prelude ((-)) import Fold.Shortcut.Conversion (fold) import Fold.Shortcut.Utilities (demotivate)+import Numeric.Natural (Natural)+import Prelude ((-))+import Strict (isAlive, isDead)  import qualified Fold.Pure.Examples.Interesting as Fold @@ -26,8 +27,7 @@ null = ShortcutFold   { initial = Alive Tenacious ()   , step = \() _ -> Dead ()-  , extractLive = \() -> True-  , extractDead = \() -> False+  , extract = isAlive   }  {-| 'True' if all inputs are 'True' (tenacious) -}@@ -35,8 +35,7 @@ and = ShortcutFold   { initial = Alive Tenacious ()   , step = \_ a -> if a then Alive Tenacious () else Dead ()-  , extractLive = \() -> True-  , extractDead = \() -> False+  , extract = isAlive   }  {-| 'True' if any input is 'True' (tenacious) -}@@ -44,8 +43,7 @@ or = ShortcutFold   { initial = Alive Tenacious ()   , step = \() a -> if a then Dead () else Alive Tenacious ()-  , extractLive = \() -> False-  , extractDead = \() -> True+  , extract = isDead   }  {-| 'True' if all inputs satisfy the predicate (tenacious) -}@@ -53,8 +51,7 @@ all predicate = ShortcutFold   { initial = Alive Tenacious ()   , step = \() a -> if predicate a then Alive Tenacious () else Dead ()-  , extractLive = \() -> True-  , extractDead = \() -> False+  , extract = isAlive   }  {-| 'True' if any input satisfies the predicate (tenacious) -}@@ -62,8 +59,7 @@ any predicate = ShortcutFold   { initial = Alive Tenacious ()   , step = \_ a -> if predicate a then Dead () else Alive Tenacious ()-  , extractLive = \() -> False-  , extractDead = \() -> True+  , extract = isDead   }  {-| 'True' if any input is equal to the given value (tenacious) -}@@ -79,8 +75,7 @@ find ok = ShortcutFold     { initial = Alive Tenacious ()     , step = \() a -> if ok a then Dead a else Alive Tenacious ()-    , extractDead = Just-    , extractLive = \() -> Nothing+    , extract = \v -> case v of { Dead x -> Just x; _ -> Nothing }     }  {-| The /n/th input, where n=0 is the first input, if the index is in@@ -89,8 +84,7 @@ index i = ShortcutFold     { initial = Alive Tenacious i     , step = \i' a -> if i' == 0 then Dead a else Alive Tenacious (i' - 1)-    , extractDead = Just-    , extractLive = \_ -> Nothing+    , extract = \v -> case v of { Dead x -> Just x; _ -> Nothing }     }  {-| The index of the first input that matches the given value, if any@@ -113,6 +107,5 @@ lookup a0 = ShortcutFold     { initial = Alive Tenacious ()     , step = \() (a, b) -> if a == a0 then Dead b else Alive Tenacious ()-    , extractLive = \() -> Nothing-    , extractDead = Just+    , extract = \v -> case v of { Dead x -> Just x; _ -> Nothing }     }
source/Fold/Shortcut/Run.hs view
@@ -3,11 +3,9 @@ import Fold.Shortcut.Type  {-| Fold a listlike container to a single summary result, forcing-    only enough input to satisfy the short-cutting fold -}+    only enough input to satisfy the short-cutting fold's tenacity -} run :: ShortcutFold a b -> [a] -> b-run ShortcutFold{ initial, step, extractDead, extractLive } = go initial+run ShortcutFold{ initial, step, extract } = go initial   where-    go (Alive Tenacious x) (a : as)  =  go (step x a) as-    go (Alive Tenacious x) []        =  extractLive x-    go (Alive Ambivalent x) _        =  extractLive x-    go (Dead x)             _        =  extractDead x+    go (Alive Tenacious x) (a : as) = go (step x a) as+    go v _ = extract v
source/Fold/Shortcut/Type.hs view
@@ -19,43 +19,32 @@ data ShortcutFold a b = forall x y. ShortcutFold     { initial :: Vitality x y     , step :: y -> a -> Vitality x y-    , extractDead :: x -> b-    , extractLive :: y -> b+    , extract :: Vitality x y -> b     }  instance Functor (ShortcutFold a) where-    fmap f ShortcutFold{ step, initial, extractDead, extractLive } =-        ShortcutFold-          { initial-          , step-          , extractDead = \x -> f (extractDead x)-          , extractLive = \x -> f (extractLive x)-          }+    fmap f ShortcutFold{ step, initial, extract } =+        ShortcutFold{ initial, step, extract = \x -> f (extract x) }  instance Applicative (ShortcutFold a) where     pure b = ShortcutFold         { initial = Dead ()         , step = absurd-        , extractDead = \() -> b-        , extractLive = absurd+        , extract = \e -> case e of { Dead () -> b }         }      (<*>)-        ShortcutFold{ initial = initialL, step = stepL, extractDead = extractDeadL, extractLive = extractLiveL }-        ShortcutFold{ initial = initialR, step = stepR, extractDead = extractDeadR, extractLive = extractLiveR } =+        ShortcutFold{ initial = initialL, step = stepL, extract = extractL }+        ShortcutFold{ initial = initialR, step = stepR, extract = extractR } =           ShortcutFold             { initial = Strict.vitality2 initialL initialR             , step = \(Strict.Tuple2 xL xR) a -> Strict.vitality2                 (Strict.unlessDead (\x -> stepL x a) xL)                 (Strict.unlessDead (\x -> stepR x a) xR)-            , extractDead = extract-            , extractLive = extract+            , extract = \e -> case e of { Dead x -> ex x; Alive _ x -> ex x }             }           where-            extract(Strict.Tuple2 xL xR) = f x-              where-                f = case xL of { Dead a -> extractDeadL a; Alive _ b -> extractLiveL b }-                x = case xR of { Dead a -> extractDeadR a; Alive _ b -> extractLiveR b }+            ex (Strict.Tuple2 xL xR) = (extractL xL) (extractR xR)  instance Semigroup b => Semigroup (ShortcutFold a b) where     (<>) = liftA2 (<>)
source/Fold/Shortcut/Utilities.hs view
@@ -8,12 +8,23 @@  {-| Causes a shortcut fold to stop once it becomes ambivalent -} demotivate :: ShortcutFold a b -> ShortcutFold a b-demotivate ShortcutFold{ initial, step, extractDead, extractLive } =+demotivate ShortcutFold{ initial, step, extract } =   ShortcutFold     { initial = willSave initial     , step = \x a -> willSave (step x a)-    , extractDead = \e -> case e of-          Strict.Left x -> extractDead x-          Strict.Right x -> extractLive x-    , extractLive = extractLive+    , extract = \v -> case v of+        Dead e -> case e of+          Strict.Left x -> extract (Dead x)+          Strict.Right x -> extract (Alive Ambivalent x)+        Alive w x -> extract (Alive w x)+    }++{-| Allows to continue feeding a fold even after passing it to a function+that closes it -}+duplicate :: ShortcutFold a b -> ShortcutFold a (ShortcutFold a b)+duplicate ShortcutFold{ initial, step, extract } =+  ShortcutFold+    { initial+    , step+    , extract = \v -> ShortcutFold{ initial = v, step, extract }     }
source/Fold/ShortcutNonempty.hs view
@@ -17,7 +17,7 @@      {- * Conversion -} fold, effectfulFold, nonemptyFold, shortcutFold, -    {- * Utilities -} demotivate,+    {- * Utilities -} demotivate, duplicate,   )   where 
source/Fold/ShortcutNonempty/Conversion.hs view
@@ -21,8 +21,7 @@     ShortcutNonemptyFold       { initial = \a -> Alive Ambivalent (step initial a)       , step = \x a -> Alive Ambivalent (step x a)-      , extractDead = absurd-      , extractLive = extract+      , extract = \v -> case v of { Alive _ x -> extract x; Dead x -> absurd x }       }  effectfulFold :: EffectfulFold Identity a b -> ShortcutNonemptyFold a b@@ -34,18 +33,16 @@     ShortcutNonemptyFold       { initial = \a -> Alive Ambivalent (initial a)       , step = \x a -> Alive Ambivalent (step x a)-      , extractDead = absurd-      , extractLive = extract+      , extract = \v -> case v of { Alive _ x -> extract x; Dead x -> absurd x }       }  shortcutFold :: ShortcutFold a b -> ShortcutNonemptyFold a b shortcutFold ShortcutFold{ Shortcut.initial, Shortcut.step,-        Shortcut.extractDead, Shortcut.extractLive } =+        Shortcut.extract } =     ShortcutNonemptyFold       { initial = case initial of             Dead    x -> \_ -> Dead x             Alive _ x -> step x       , step = step-      , extractDead = extractDead-      , extractLive = extractLive+      , extract       }
source/Fold/ShortcutNonempty/Examples/Interesting.hs view
@@ -6,7 +6,6 @@  import Fold.ShortcutNonempty.Type -import Data.Function (id) import Data.Void (absurd)  {-| The first input (tenacious) -}@@ -14,6 +13,5 @@ first = ShortcutNonemptyFold   { initial = Dead   , step = absurd-  , extractDead = id-  , extractLive = absurd+  , extract = \v -> case v of { Dead x -> x }   }
source/Fold/ShortcutNonempty/Run.hs view
@@ -5,12 +5,10 @@ import Data.List.NonEmpty (NonEmpty ((:|)))  {-| Fold a nonempty listlike container to a single summary result,-    forcing only enough input to satisfy the short-cutting fold -}+    forcing only enough input to satisfy the short-cutting fold's tenacity -} run :: ShortcutNonemptyFold a b -> NonEmpty a -> b-run ShortcutNonemptyFold{ initial, step, extractDead, extractLive } =+run ShortcutNonemptyFold{ initial, step, extract } =     \(z :| as) -> go (initial z) as   where-    go (Alive Tenacious x)  (a : as)  =  go (step x a) as-    go (Alive Tenacious x)  []        =  extractLive x-    go (Alive Ambivalent x) _         =  extractLive x-    go (Dead x)             _         =  extractDead x+    go (Alive Tenacious x) (a : as) = go (step x a) as+    go v _ = extract v
source/Fold/ShortcutNonempty/Type.hs view
@@ -19,43 +19,32 @@ data ShortcutNonemptyFold a b = forall x y. ShortcutNonemptyFold     { initial :: a -> Vitality x y     , step :: y -> a -> Vitality x y-    , extractDead :: x -> b-    , extractLive :: y -> b+    , extract :: Vitality x y -> b     }  instance Functor (ShortcutNonemptyFold a) where-    fmap f ShortcutNonemptyFold{ step, initial, extractDead, extractLive } =-        ShortcutNonemptyFold-          { initial-          , step-          , extractDead = \x -> f (extractDead x)-          , extractLive = \x -> f (extractLive x)-          }+    fmap f ShortcutNonemptyFold{ step, initial, extract } =+        ShortcutNonemptyFold{ initial, step, extract = \x -> f (extract x) }  instance Applicative (ShortcutNonemptyFold a) where     pure b = ShortcutNonemptyFold         { initial = \_ -> Dead ()         , step = absurd-        , extractDead = \() -> b-        , extractLive = absurd+        , extract = \e -> case e of { Dead () -> b }         }      (<*>)-        ShortcutNonemptyFold{ initial = initialL, step = stepL, extractDead = extractDeadL, extractLive = extractLiveL }-        ShortcutNonemptyFold{ initial = initialR, step = stepR, extractDead = extractDeadR, extractLive = extractLiveR } =+        ShortcutNonemptyFold{ initial = initialL, step = stepL, extract = extractL }+        ShortcutNonemptyFold{ initial = initialR, step = stepR, extract = extractR } =           ShortcutNonemptyFold             { initial = \a -> Strict.vitality2 (initialL a) (initialR a)             , step = \(Strict.Tuple2 xL xR) a -> Strict.vitality2                 (Strict.unlessDead (\x -> stepL x a) xL)                 (Strict.unlessDead (\x -> stepR x a) xR)-            , extractDead = extract-            , extractLive = extract+            , extract = \e -> case e of { Dead x -> ex x; Alive _ x -> ex x }             }           where-            extract(Strict.Tuple2 xL xR) = f x-              where-                f = case xL of { Dead a -> extractDeadL a; Alive _ b -> extractLiveL b }-                x = case xR of { Dead a -> extractDeadR a; Alive _ b -> extractLiveR b }+            ex (Strict.Tuple2 xL xR) = (extractL xL) (extractR xR)  instance Semigroup b => Semigroup (ShortcutNonemptyFold a b) where     (<>) = liftA2 (<>)
source/Fold/ShortcutNonempty/Utilities.hs view
@@ -2,18 +2,31 @@  import Fold.ShortcutNonempty.Type +import Fold.Shortcut.Type (ShortcutFold (ShortcutFold)) import Strict (willSave)  import qualified Strict+import qualified Fold.Shortcut.Type as Empty  {-| Causes a shortcut fold to stop once it becomes ambivalent -} demotivate :: ShortcutNonemptyFold a b -> ShortcutNonemptyFold a b-demotivate ShortcutNonemptyFold{ initial, step, extractDead, extractLive } =+demotivate ShortcutNonemptyFold{ initial, step, extract } =   ShortcutNonemptyFold     { initial = \a -> willSave (initial a)     , step = \x a -> willSave (step x a)-    , extractDead = \e -> case e of-          Strict.Left x -> extractDead x-          Strict.Right x -> extractLive x-    , extractLive = extractLive+    , extract = \v -> case v of+        Dead e -> case e of+          Strict.Left x -> extract (Dead x)+          Strict.Right x -> extract (Alive Ambivalent x)+        Alive w x -> extract (Alive w x)+    }++{-| Allows to continue feeding a fold even after passing it to a function+that closes it -}+duplicate :: ShortcutNonemptyFold a b -> ShortcutNonemptyFold a (ShortcutFold a b)+duplicate ShortcutNonemptyFold{ initial, step, extract } =+  ShortcutNonemptyFold+    { initial+    , step+    , extract = \v -> ShortcutFold{ Empty.initial = v, Empty.step, Empty.extract }     }
source/Strict.hs view
@@ -8,10 +8,11 @@     {- * Either -} Either (..), hush,     {- * Tuples -} Tuple2 (..), Tuple3 (..),     {- * Shortcut -} Vitality (..), Will (..),-        unlessDead, vitality2, willSave,+        unlessDead, vitality2, willSave, isAlive, isDead,   )   where +import Data.Bool (Bool (..)) import Data.Functor (Functor (..)) import Data.Monoid (Monoid, mempty) import Data.Semigroup (Semigroup, (<>))@@ -76,3 +77,9 @@ vitality2 a@(Dead _)     b@(Alive v _)  = Alive v          (Strict.Tuple2 a b) vitality2 a@(Alive v _)  b@(Dead _)     = Alive v          (Strict.Tuple2 a b) vitality2 a@(Dead _)     b@(Dead _)     = Dead             (Strict.Tuple2 a b)++isAlive :: Vitality a b -> Bool+isAlive v = case v of { Alive _ _ -> True; Dead _ -> False }++isDead :: Vitality a b -> Bool+isDead v = case v of { Alive _ _ -> False; Dead _ -> True }
test/Spec/Effectful.hs view
@@ -6,6 +6,7 @@  import Control.Applicative (pure, (<*>)) import Control.Monad ((<=<))+import Data.Bool (Bool (..)) import Data.Foldable (traverse_) import Data.Function (id, on, (.), (&)) import Data.Functor ((<$>))@@ -13,7 +14,6 @@ import Data.Monoid (mempty) import Data.Semigroup (Sum (Sum), (<>)) import Prelude ((>), String, Integer, (+), (*))-import Data.Bool (Bool (..))  import qualified Data.List as List 
test/Spec/Nonempty.hs view
@@ -4,10 +4,14 @@  import Test.Hspec +import Data.Function ((&), flip) import Data.List.NonEmpty (NonEmpty ((:|))) import Positive (Positive) import Prelude (String, Integer) +import qualified Data.List as List+import qualified Fold.Pure as Pure+ spec :: SpecWith () spec = describe "NonemptyFold" do @@ -41,3 +45,12 @@             run sum [1,2,5] `shouldBe` (8 :: Positive)         it "product works with Positive" do             run product [1,2,5] `shouldBe` (10 :: Positive)++    describe "duplicate" do+        it "lets a fold run in two phases" do+            let a, c :: NonEmpty Integer+                b :: [Integer]+                a = [1..3]+                b = [4..6]+                c = [1..6]+            (sum & duplicate & flip run a & flip Pure.run b) `shouldBe` (List.sum c)
test/Spec/Pure.hs view
@@ -5,14 +5,14 @@ import Test.Hspec  import Control.Applicative (pure, (<*>))+import Data.Bool (Bool (..)) import Data.Foldable (traverse_)-import Data.Function (id, on, (.), (&))+import Data.Function (id, on, (.), (&), flip) import Data.Functor ((<$>)) import Data.Maybe (Maybe (Just, Nothing)) import Data.Monoid (mempty) import Data.Semigroup (Sum (Sum)) import Prelude ((>), String, Integer, (+), (*))-import Data.Bool (Bool (..))  import qualified Data.Foldable as Foldable import qualified Data.List as List@@ -137,3 +137,11 @@             run null ([1] :: [Integer]) `shouldBe` False             run null ([1,2] :: [Integer]) `shouldBe` False             run null ([1,2,3] :: [Integer]) `shouldBe` False++    describe "duplicate" do+        it "lets a fold run in two phases" do+            let a, b, c :: [Integer]+                a = [1..3]+                b = [4..6]+                c = [1..6]+            (sum & duplicate & flip run a & flip run b) `shouldBe` (List.sum c)
test/Spec/Shortcut.hs view
@@ -5,10 +5,12 @@ import Test.Hspec  import Control.Applicative (pure, (<$>), (<*>))-import Prelude (Integer, undefined)-import Data.Maybe (Maybe (Just, Nothing))-import Data.List ((++)) import Data.Bool (Bool (..))+import Data.Function ((&), flip)+import Data.List ((++))+import Data.Maybe (Maybe (Just, Nothing))+import Data.Ord (Ord (..))+import Prelude (Integer, undefined)  import qualified Data.Char as Char @@ -79,3 +81,18 @@             run or [True,False] `shouldBe` True         it "is lazy" do             run or (True : undefined) `shouldBe` True++    describe "duplicate" do+        it "lets a fold run in two phases" do+            let a, b, c :: [Integer]+                a = [1,2,3]+                b = [4,7,12,15]+                c = a ++ b+                f = find (>= 10)+            (f & duplicate & flip run a & flip run b) `shouldBe` (run f c)+        it "preserves laziness" do+            let a, b :: [Integer]+                a = 1 : 15 : undefined+                b = undefined+                f = find (>= 10)+            (f & duplicate & flip run a & flip run b) `shouldBe` Just 15
test/Spec/ShortcutNonempty.hs view
@@ -6,13 +6,16 @@  import Control.Applicative (pure, (<$>), (<*>), liftA2) import Data.Bool (Bool (..))+import Data.Function ((&), flip) import Data.List ((++)) import Data.List.NonEmpty (NonEmpty ((:|)))-import Data.Maybe (Maybe (Just))+import Data.Maybe (Maybe (..))+import Data.Ord (Ord (..)) import Positive (Positive) import Prelude (Integer, undefined)  import qualified Data.Char as Char+import qualified Fold.Shortcut as Empty  spec :: SpecWith () spec = describe "ShortcutNonemptyFold" do@@ -64,3 +67,19 @@             run (liftA2 (,) (index 2) sum) [1,2,5,7] `shouldBe` (Just 5, 8 :: Positive)         it "product works with Positive" do             run (liftA2 (,) (index 2) product) [1,2,5,3] `shouldBe` (Just 5, 10 :: Positive)++    describe "duplicate" do+        it "lets a fold run in two phases" do+            let a :: NonEmpty Integer+                b :: [Integer]+                a = [1,2,3]+                b = [4,7,12,15]+                f = find (>= 10)+            (f & duplicate & flip run a & flip Empty.run b) `shouldBe` Just 12+        it "preserves laziness" do+            let a :: NonEmpty Integer+                b :: [Integer]+                a = 1 :| 15 : undefined+                b = undefined+                f = find (>= 10)+            (f & duplicate & flip run a & flip Empty.run b) `shouldBe` Just 15