packages feed

list-t 0.2.7 → 0.3.0

raw patch · 4 files changed

+170/−172 lines, 4 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- ListT: class MonadPlus m => ListMonad m
- ListT: class MonadTrans t => ListTrans t
- ListT: instance ListMonad []
- ListT: instance ListMonad m => ListMonad (ReaderT e m)
- ListT: instance ListTrans ListT
- ListT: instance Monad m => ListMonad (ListT m)
+ ListT: class MonadPlus m => MonadCons m
+ ListT: class MonadTrans t => MonadTransUncons t
+ ListT: instance Monad m => MonadCons (ListT m)
+ ListT: instance MonadCons []
+ ListT: instance MonadCons m => MonadCons (ReaderT e m)
+ ListT: instance MonadTransUncons ListT
- ListT: cons :: ListMonad m => a -> m a -> m a
+ ListT: cons :: MonadCons m => a -> m a -> m a
- ListT: fold :: (Monad m, ListTrans t) => (r -> a -> m r) -> r -> t m a -> m r
+ ListT: fold :: (Monad m, MonadTransUncons t) => (r -> a -> m r) -> r -> t m a -> m r
- ListT: fromFoldable :: (ListMonad m, Foldable f) => f a -> m a
+ ListT: fromFoldable :: (MonadCons m, Foldable f) => f a -> m a
- ListT: head :: (Monad m, ListTrans t) => t m a -> m (Maybe a)
+ ListT: head :: (Monad m, MonadTransUncons t) => t m a -> m (Maybe a)
- ListT: null :: (Monad m, ListTrans t) => t m a -> m Bool
+ ListT: null :: (Monad m, MonadTransUncons t) => t m a -> m Bool
- ListT: repeat :: ListMonad m => a -> m a
+ ListT: repeat :: MonadCons m => a -> m a
- ListT: splitAt :: (Monad m, ListTrans t, MonadPlus (t m)) => Int -> t m a -> m ([a], t m a)
+ ListT: splitAt :: (Monad m, MonadTransUncons t, MonadPlus (t m)) => Int -> t m a -> m ([a], t m a)
- ListT: tail :: (Monad m, ListTrans t) => t m a -> m (Maybe (t m a))
+ ListT: tail :: (Monad m, MonadTransUncons t) => t m a -> m (Maybe (t m a))
- ListT: toList :: (Monad m, ListTrans t) => t m a -> m [a]
+ ListT: toList :: (Monad m, MonadTransUncons t) => t m a -> m [a]
- ListT: toReverseList :: (Monad m, ListTrans t) => t m a -> m [a]
+ ListT: toReverseList :: (Monad m, MonadTransUncons t) => t m a -> m [a]
- ListT: traverse_ :: (Monad m, ListTrans t) => (a -> m ()) -> t m a -> m ()
+ ListT: traverse_ :: (Monad m, MonadTransUncons t) => (a -> m ()) -> t m a -> m ()
- ListT: type Transformation m a b = forall t. (Monad m, ListMonad (t m), ListTrans t) => t m a -> t m b
+ ListT: type Transformation m a b = forall t. (Monad m, MonadCons (t m), MonadTransUncons t) => t m a -> t m b
- ListT: uncons :: ListTrans t => t m a -> m (Maybe (a, t m a))
+ ListT: uncons :: (MonadTransUncons t, Monad m) => t m a -> m (Maybe (a, t m a))
- ListT: unfold :: ListMonad m => (b -> Maybe (a, b)) -> b -> m a
+ ListT: unfold :: MonadCons m => (b -> Maybe (a, b)) -> b -> m a

Files

− executables/APITests.hs
@@ -1,137 +0,0 @@-{-# OPTIONS_GHC -F -pgmF htfpp #-}--import BasePrelude hiding (toList)-import MTLPrelude-import Test.Framework-import qualified ListT as L---main = htfMain $ htf_thisModulesTests----- * Applicative----------------------------prop_applicativeIdentityLaw (l :: [Int]) =-  runIdentity $ streamsEqual (pure id <*> s) s-  where-    s = L.fromFoldable l--prop_applicativeBehavesLikeList =-  \(ns :: [Int]) ->-    let a = fs <*> ns-        b = runIdentity (toList $ L.fromFoldable fs <*> L.fromFoldable ns)-        in a == b-  where-    fs = [(+1), (+3), (+5)]----- * Monad----------------------------test_monadLaw1 =-  assertBool =<< streamsEqual (return a >>= k) (k a)-  where-    a = 2-    k a = return $ chr a--test_monadLaw2 =-  assertBool =<< streamsEqual (m >>= return) m-  where-    m = L.fromFoldable ['a'..'z']--test_monadLaw3 =-  assertBool =<< streamsEqual (m >>= (\x -> k x >>= h)) ((m >>= k) >>= h)-  where-    m = L.fromFoldable ['a'..'z']-    k a = return $ ord a-    h a = return $ a + 1--test_monadLaw4 =-  assertBool =<< streamsEqual (fmap f xs) (xs >>= return . f)-  where-    f = ord-    xs = L.fromFoldable ['a'..'z']----- * Monoid----------------------------test_mappend =-  assertBool =<< -    streamsEqual -      (L.fromFoldable [0..7]) -      (L.fromFoldable [0..3] <> L.fromFoldable [4..7])--test_mappendAndTake =-  assertBool =<< -    streamsEqual -      (L.fromFoldable [0..5]) -      (L.take 6 $ L.fromFoldable [0..3] <> L.fromFoldable [4..7])--test_mappendDoesntCauseTraversal =-  do-    ref <- newIORef 0-    (flip runReaderT) ref (toList $ L.take 5 $ stream <> stream)-    assertEqual 5 =<< readIORef ref-  where-    stream =-      do-        ref <- lift $ ask-        x <- L.fromFoldable [0..4]-        liftIO $ modifyIORef ref (+1)-        return x----- * Other----------------------------test_repeat =-  assertEqual [2,2,2] =<< do-    toList $ L.take 3 $ L.repeat (2 :: Int)--test_traverseDoesntCauseTraversal =-  do-    ref <- newIORef 0-    (flip runReaderT) ref (toList stream3)-    assertEqual 3 =<< readIORef ref-  where-    stream1 =-      do-        ref <- lift $ ask-        x <- L.fromFoldable ['a'..'z']-        liftIO $ modifyIORef ref (+1)-        return x-    stream2 =-      L.traverse (return . toUpper) stream1-    stream3 =-      L.take 3 stream2--test_takeDoesntCauseTraversal =-  do-    ref <- newIORef 0-    (flip runReaderT) ref (toList $ L.take 3 $ L.take 7 $ stream)-    assertEqual 3 =<< readIORef ref-  where-    stream =-      do-        ref <- lift $ ask-        x <- L.fromFoldable [0..10]-        liftIO $ modifyIORef ref (+1)-        return x--test_drop =-  assertEqual [3, 4] =<< do-    toList $ L.drop 2 $ L.fromFoldable [1 .. 4]-    -test_slice =-  assertEqual ["abc", "def", "gh"] =<< do-    toList $ L.slice (fromJust $ L.positive 3) $ L.fromFoldable ("abcdefgh" :: [Char])---toList :: Monad m => L.ListT m a -> m [a]-toList = L.toList--streamsEqual :: (Applicative m, Monad m, Eq a) => L.ListT m a -> L.ListT m a -> m Bool-streamsEqual a b =-  (==) <$> L.toList a <*> L.toList b
library/ListT.hs view
@@ -3,8 +3,8 @@ (   ListT,   -- * Classes-  ListTrans(..),-  ListMonad(..),+  MonadTransUncons(..),+  MonadCons(..),   -- * Execution utilities   head,   tail,@@ -35,7 +35,7 @@ ) where -import BasePrelude hiding (uncons, toList, yield, fold, traverse, head, tail, take, drop, repeat, null, traverse_, splitAt)+import BasePrelude hiding (toList, yield, fold, traverse, head, tail, take, drop, repeat, null, traverse_, splitAt) import Control.Monad.Morph hiding (MonadTrans(..)) import Control.Monad.IO.Class import Control.Monad.Trans.Class@@ -44,7 +44,7 @@ import Control.Monad.Base  -- |--- A proper implementation of a list monad-transformer.+-- A proper implementation of the list monad-transformer. -- Useful for streaming of monadic data structures. --  -- Since it has instances of 'MonadPlus' and 'Alternative',@@ -133,34 +133,34 @@ -------------------------  -- |--- A monad transformer capable of executing like a list.-class MonadTrans t => ListTrans t where+-- A monad transformer capable of deconstructing like a list.+class MonadTrans t => MonadTransUncons t where   -- |   -- Execute in the inner monad,   -- getting the head and the tail.   -- Returns nothing if it's empty.-  uncons :: t m a -> m (Maybe (a, t m a))+  uncons :: Monad m => t m a -> m (Maybe (a, t m a)) -instance ListTrans ListT where+instance MonadTransUncons ListT where   {-# INLINE uncons #-}   uncons (ListT m) = m   -- | -- A monad capable of constructing like a list.-class MonadPlus m => ListMonad m where+class MonadPlus m => MonadCons m where   -- |   -- Prepend an element.   cons :: a -> m a -> m a -instance ListMonad [] where+instance MonadCons [] where   cons a m = a : m -instance Monad m => ListMonad (ListT m) where+instance Monad m => MonadCons (ListT m) where   {-# INLINABLE cons #-}   cons h t = ListT $ return (Just (h, t)) -instance ListMonad m => ListMonad (ReaderT e m) where+instance MonadCons m => MonadCons (ReaderT e m) where   cons a m = ReaderT $ cons a . runReaderT m  @@ -170,35 +170,35 @@ -- | -- Execute, getting the head. Returns nothing if it's empty. {-# INLINABLE head #-}-head :: (Monad m, ListTrans t) => t m a -> m (Maybe a)+head :: (Monad m, MonadTransUncons t) => t m a -> m (Maybe a) head =   liftM (fmap fst) . uncons  -- | -- Execute, getting the tail. Returns nothing if it's empty. {-# INLINABLE tail #-}-tail :: (Monad m, ListTrans t) => t m a -> m (Maybe (t m a))+tail :: (Monad m, MonadTransUncons t) => t m a -> m (Maybe (t m a)) tail =   liftM (fmap snd) . uncons  -- | -- Execute, checking whether it's empty. {-# INLINABLE null #-}-null :: (Monad m, ListTrans t) => t m a -> m Bool+null :: (Monad m, MonadTransUncons t) => t m a -> m Bool null =   liftM (maybe True (const False)) . uncons  -- | -- Execute, applying a left fold. {-# INLINABLE fold #-}-fold :: (Monad m, ListTrans t) => (r -> a -> m r) -> r -> t m a -> m r+fold :: (Monad m, MonadTransUncons t) => (r -> a -> m r) -> r -> t m a -> m r fold s r =    uncons >=> maybe (return r) (\(h, t) -> s r h >>= \r' -> fold s r' t)  -- | -- Execute, folding to a list. {-# INLINABLE toList #-}-toList :: (Monad m, ListTrans t) => t m a -> m [a]+toList :: (Monad m, MonadTransUncons t) => t m a -> m [a] toList =   liftM ($ []) . fold (\f e -> return $ f . (e :)) id @@ -206,21 +206,21 @@ -- Execute, folding to a list in a reverse order. -- Performs more efficiently than 'toList'. {-# INLINABLE toReverseList #-}-toReverseList :: (Monad m, ListTrans t) => t m a -> m [a]+toReverseList :: (Monad m, MonadTransUncons t) => t m a -> m [a] toReverseList =   ListT.fold (\l -> return . (:l)) []  -- | -- Execute, traversing the stream with a side effect in the inner monad.  {-# INLINABLE traverse_ #-}-traverse_ :: (Monad m, ListTrans t) => (a -> m ()) -> t m a -> m ()+traverse_ :: (Monad m, MonadTransUncons t) => (a -> m ()) -> t m a -> m () traverse_ f =   fold (const f) ()  -- | -- Execute, consuming a list of the specified length and returning the remainder stream. {-# INLINABLE splitAt #-}-splitAt :: (Monad m, ListTrans t, MonadPlus (t m)) => Int -> t m a -> m ([a], t m a)+splitAt :: (Monad m, MonadTransUncons t, MonadPlus (t m)) => Int -> t m a -> m ([a], t m a) splitAt =   \case     n | n > 0 -> \l ->@@ -239,21 +239,21 @@ -- | -- Construct from any foldable. {-# INLINABLE fromFoldable #-}-fromFoldable :: (ListMonad m, Foldable f) => f a -> m a+fromFoldable :: (MonadCons m, Foldable f) => f a -> m a fromFoldable =    foldr cons mzero  -- | -- Construct by unfolding a pure data structure. {-# INLINABLE unfold #-}-unfold :: (ListMonad m) => (b -> Maybe (a, b)) -> b -> m a+unfold :: (MonadCons m) => (b -> Maybe (a, b)) -> b -> m a unfold f s =   maybe mzero (\(h, t) -> cons h (unfold f t)) (f s)  -- | -- Produce an infinite stream. {-# INLINABLE repeat #-}-repeat :: (ListMonad m) => a -> m a+repeat :: (MonadCons m) => a -> m a repeat =    fix . cons @@ -262,18 +262,16 @@ -------------------------  -- |--- A transformation function on a list transformer.--- It may update the structure or the result type, --- but the type of the transformer remains the same.+-- A function, which updates the contents of a list transformer. --  -- Since it's merely just a function, -- you can run it by passing a list transformer as an argument. type Transformation m a b = -  forall t. (Monad m, ListMonad (t m), ListTrans t) =>+  forall t. (Monad m, MonadCons (t m), MonadTransUncons t) =>   t m a -> t m b  -- |--- Produce a transformation,+-- A transformation, -- which traverses the stream with an action in the inner monad. {-# INLINABLE traverse #-} traverse :: (a -> m b) -> Transformation m a b@@ -283,7 +281,7 @@   maybe mzero return  -- |--- Produce a transformation,+-- A transformation, -- reproducing the behaviour of @Data.List.'Data.List.take'@. {-# INLINABLE take #-} take :: Int -> Transformation m a a@@ -298,7 +296,7 @@       const $ mzero  -- |--- Produce a transformation,+-- A transformation, -- reproducing the behaviour of @Data.List.'Data.List.drop'@. {-# INLINABLE drop #-} drop :: Int -> Transformation m a a@@ -310,7 +308,7 @@       id  -- |--- Produce a transformation,+-- A transformation, -- which slices a list into chunks of the specified length. {-# INLINABLE slice #-} slice :: Positive Int -> Transformation m a [a]
list-t.cabal view
@@ -1,7 +1,7 @@ name:   list-t version:-  0.2.7+  0.3.0 synopsis:   ListT done right description:@@ -54,13 +54,13 @@     Haskell2010  -test-suite api-tests+test-suite tests   type:     exitcode-stdio-1.0   hs-source-dirs:-    executables+    tests   main-is:-    APITests.hs+    Main.hs   build-depends:     list-t,     HTF == 0.12.*,
+ tests/Main.hs view
@@ -0,0 +1,137 @@+{-# OPTIONS_GHC -F -pgmF htfpp #-}++import BasePrelude hiding (toList)+import MTLPrelude+import Test.Framework+import qualified ListT as L+++main = htfMain $ htf_thisModulesTests+++-- * Applicative+-------------------------++prop_applicativeIdentityLaw (l :: [Int]) =+  runIdentity $ streamsEqual (pure id <*> s) s+  where+    s = L.fromFoldable l++prop_applicativeBehavesLikeList =+  \(ns :: [Int]) ->+    let a = fs <*> ns+        b = runIdentity (toList $ L.fromFoldable fs <*> L.fromFoldable ns)+        in a == b+  where+    fs = [(+1), (+3), (+5)]+++-- * Monad+-------------------------++test_monadLaw1 =+  assertBool =<< streamsEqual (return a >>= k) (k a)+  where+    a = 2+    k a = return $ chr a++test_monadLaw2 =+  assertBool =<< streamsEqual (m >>= return) m+  where+    m = L.fromFoldable ['a'..'z']++test_monadLaw3 =+  assertBool =<< streamsEqual (m >>= (\x -> k x >>= h)) ((m >>= k) >>= h)+  where+    m = L.fromFoldable ['a'..'z']+    k a = return $ ord a+    h a = return $ a + 1++test_monadLaw4 =+  assertBool =<< streamsEqual (fmap f xs) (xs >>= return . f)+  where+    f = ord+    xs = L.fromFoldable ['a'..'z']+++-- * Monoid+-------------------------++test_mappend =+  assertBool =<< +    streamsEqual +      (L.fromFoldable [0..7]) +      (L.fromFoldable [0..3] <> L.fromFoldable [4..7])++test_mappendAndTake =+  assertBool =<< +    streamsEqual +      (L.fromFoldable [0..5]) +      (L.take 6 $ L.fromFoldable [0..3] <> L.fromFoldable [4..7])++test_mappendDoesntCauseTraversal =+  do+    ref <- newIORef 0+    (flip runReaderT) ref (toList $ L.take 5 $ stream <> stream)+    assertEqual 5 =<< readIORef ref+  where+    stream =+      do+        ref <- lift $ ask+        x <- L.fromFoldable [0..4]+        liftIO $ modifyIORef ref (+1)+        return x+++-- * Other+-------------------------++test_repeat =+  assertEqual [2,2,2] =<< do+    toList $ L.take 3 $ L.repeat (2 :: Int)++test_traverseDoesntCauseTraversal =+  do+    ref <- newIORef 0+    (flip runReaderT) ref (toList stream3)+    assertEqual 3 =<< readIORef ref+  where+    stream1 =+      do+        ref <- lift $ ask+        x <- L.fromFoldable ['a'..'z']+        liftIO $ modifyIORef ref (+1)+        return x+    stream2 =+      L.traverse (return . toUpper) stream1+    stream3 =+      L.take 3 stream2++test_takeDoesntCauseTraversal =+  do+    ref <- newIORef 0+    (flip runReaderT) ref (toList $ L.take 3 $ L.take 7 $ stream)+    assertEqual 3 =<< readIORef ref+  where+    stream =+      do+        ref <- lift $ ask+        x <- L.fromFoldable [0..10]+        liftIO $ modifyIORef ref (+1)+        return x++test_drop =+  assertEqual [3, 4] =<< do+    toList $ L.drop 2 $ L.fromFoldable [1 .. 4]+    +test_slice =+  assertEqual ["abc", "def", "gh"] =<< do+    toList $ L.slice (fromJust $ L.positive 3) $ L.fromFoldable ("abcdefgh" :: [Char])+++toList :: Monad m => L.ListT m a -> m [a]+toList = L.toList++streamsEqual :: (Applicative m, Monad m, Eq a) => L.ListT m a -> L.ListT m a -> m Bool+streamsEqual a b =+  (==) <$> L.toList a <*> L.toList b