packages feed

list-t-0.4.0: tests/Main.hs

{-# 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