ilist-0.3.0.0: tests/Main.hs
import Control.Exception
import Control.Monad
import Control.Monad.Trans.State.Lazy
import Data.List
import Data.List.Index
import Test.Hspec
main :: IO ()
main = hspec $ do
newFunctions
transformations
monadicFunctions
specialFolds
folds
sublists
search
zipping
buildingLists
newFunctions :: Spec
newFunctions = describe "new functions" $ do
describe "indexed" $ do
specify "basic" $ do
indexed [1,2,3] `shouldBe` [(0,1),(1,2),(2,3::Int)]
specify "empty" $ do
indexed [] `shouldBe` ([] :: [(Int,Bool)])
specify "undefined" $ do
take 1 (indexed (1:undefined)) `shouldBe` [(0,1::Int)]
specify "infinite" $ do
take 2 (indexed [1..]) `shouldBe` [(0,1),(1,2::Int)]
describe "deleteAt" $ do
specify "basic" $ do
deleteAt 0 [0,1,2] `shouldBe` [1,2::Int]
deleteAt 1 [0,1,2] `shouldBe` [0,2::Int]
specify "empty" $ do
deleteAt 0 [] `shouldBe` ([]::[Bool])
specify "undefined" $ do
take 1 (deleteAt 0 (1:2:undefined)) `shouldBe` [2::Int]
specify "infinite" $ do
take 2 (deleteAt 1 [1..]) `shouldBe` [1,3::Int]
specify "negative" $ do
deleteAt (-1) [1,2] `shouldBe` [1,2::Int]
specify "excessive" $ do
deleteAt 5 [1,2] `shouldBe` [1,2::Int]
describe "setAt" $ do
specify "basic" $ do
setAt 0 8 [0,1,2] `shouldBe` [8,1,2::Int]
setAt 1 8 [0,1,2] `shouldBe` [0,8,2::Int]
specify "empty" $ do
setAt 0 undefined [] `shouldBe` ([]::[Bool])
specify "undefined" $ do
take 1 (setAt 0 8 (1:2:undefined)) `shouldBe` [8::Int]
specify "infinite" $ do
take 2 (setAt 1 8 [1..]) `shouldBe` [1,8::Int]
specify "negative" $ do
setAt (-1) undefined [1,2] `shouldBe` [1,2::Int]
specify "excessive" $ do
setAt 2 undefined [1,2] `shouldBe` [1,2::Int]
describe "modifyAt" $ do
specify "basic" $ do
modifyAt 0 succ [0,1,2] `shouldBe` [1,1,2::Int]
modifyAt 1 succ [0,1,2] `shouldBe` [0,2,2::Int]
specify "empty" $ do
modifyAt 0 undefined [] `shouldBe` ([]::[Bool])
specify "undefined" $ do
take 2 (modifyAt 0 succ (1:2:undefined)) `shouldBe` [2,2::Int]
specify "infinite" $ do
take 2 (modifyAt 1 succ [1..]) `shouldBe` [1,3::Int]
specify "negative" $ do
modifyAt (-1) undefined [1,2] `shouldBe` [1,2::Int]
specify "excessive" $ do
modifyAt 2 undefined [1,2] `shouldBe` [1,2::Int]
describe "updateAt" $ do
specify "modify" $ do
updateAt 0 (Just . succ) [0,1,2] `shouldBe` [1,1,2::Int]
updateAt 1 (Just . succ) [0,1,2] `shouldBe` [0,2,2::Int]
specify "delete" $ do
updateAt 0 (\_ -> Just 8) [0,1,2] `shouldBe` [8,1,2::Int]
updateAt 1 (\_ -> Just 8) [0,1,2] `shouldBe` [0,8,2::Int]
specify "empty" $ do
updateAt 0 undefined [] `shouldBe` ([]::[Bool])
specify "undefined" $ do
take 1 (updateAt 0 (\_ -> Just 8) (1:2:undefined)) `shouldBe` [8::Int]
specify "infinite" $ do
take 2 (updateAt 1 (\_ -> Nothing) [1..]) `shouldBe` [1,3::Int]
specify "negative" $ do
updateAt (-1) undefined [1,2] `shouldBe` [1,2::Int]
specify "excessive" $ do
updateAt 2 undefined [1,2] `shouldBe` [1,2::Int]
describe "insertAt" $ do
specify "basic" $ do
insertAt 0 8 [0,1,2] `shouldBe` [8,0,1,2::Int]
insertAt 1 8 [0,1,2] `shouldBe` [0,8,1,2::Int]
specify "end" $ do
insertAt 2 8 [1,2] `shouldBe` [1,2,8::Int]
specify "empty" $ do
insertAt 0 1 [] `shouldBe` [1::Int]
specify "undefined" $ do
take 3 (insertAt 0 8 (1:2:undefined)) `shouldBe` [8,1,2::Int]
specify "infinite" $ do
take 3 (insertAt 1 8 [1..]) `shouldBe` [1,8,2::Int]
specify "negative" $ do
insertAt (-1) 8 [1,2] `shouldBe` [1,2::Int]
specify "excessive" $ do
insertAt 3 8 [1,2] `shouldBe` [1,2::Int]
transformations :: Spec
transformations = describe "transformations" $ do
describe "imap" $ do
specify "basic" $ do
imap (-) [1,3..9] `shouldBe` [0-1,1-3,2-5,3-7,4-9]
specify "empty" $ do
imap undefined ([] :: [Int]) `shouldBe` ([] :: [Bool])
specify "x2" $ do
imap (-) (imap (*) [1..4]) `shouldBe` [0-0*1,1-1*2,2-2*3,3-3*4]
monadicFunctions :: Spec
monadicFunctions = describe "monadic functions" $ do
describe "imapM/traverse" $ do
describe "Just" $ do
specify "success" $ do
imapM (\i x -> Just (i-x)) [0..4] `shouldBe` Just [0,0,0,0,0]
itraverse (\i x -> Just (i-x)) [0..4] `shouldBe` Just [0,0,0,0,0]
specify "failure" $ do
imapM (\i x -> guard (i==x)) [0,1,2,4] `shouldBe` Nothing
itraverse (\i x -> guard (i==x)) [0,1,2,4] `shouldBe` Nothing
describe "State" $ do
specify "basic" $ do
let f i x = modify ((i,x):) >> return (i-x)
let (resA, stA) = runState (imapM f [1,3..9]) []
let (resB, stB) = runState (itraverse f [1,3..9]) []
resA `shouldBe` [0-1,1-3,2-5,3-7,4-9]
resB `shouldBe` [0-1,1-3,2-5,3-7,4-9]
stA `shouldBe` reverse (zip [0..4] [1,3..9])
stB `shouldBe` reverse (zip [0..4] [1,3..9])
describe "imapM_/traverse_" $ do
describe "Just" $ do
specify "success" $ do
imapM_ (\i x -> Just (i-x)) [0..4] `shouldBe` Just ()
itraverse_ (\i x -> Just (i-x)) [0..4] `shouldBe` Just ()
specify "failure" $ do
imapM_ (\i x -> guard (i==x)) [0,1,2,4] `shouldBe` Nothing
itraverse_ (\i x -> guard (i==x)) [0,1,2,4] `shouldBe` Nothing
describe "State" $ do
specify "basic" $ do
let f i x = modify ((i,x):) >> return (i-x)
let stA = execState (imapM_ f [1,3..9]) []
let stB = execState (itraverse_ f [1,3..9]) []
stA `shouldBe` reverse (zip [0..4] [1,3..9])
stB `shouldBe` reverse (zip [0..4] [1,3..9])
specialFolds :: Spec
specialFolds = describe "special folds" $ do
describe "iall" $ do
specify "full" $ do
iall (\i x -> i*2==x) [0,2,4,6,8] `shouldBe` True
specify "early" $ do
iall (\i x -> i*2==x) [1,2,4,6,8] `shouldBe` False
specify "empty" $ do
iall undefined ([] :: [Int]) `shouldBe` True
describe "iany" $ do
specify "full" $ do
iany (\i x -> i*2==x) [1,3,5,7,9] `shouldBe` False
specify "early" $ do
iany (\i x -> i*2==x) [0,3,5,7,9] `shouldBe` True
specify "late" $ do
iany (\i x -> i*2==x) [1,3,5,7,8] `shouldBe` True
specify "empty" $ do
iany undefined ([] :: [Int]) `shouldBe` False
folds :: Spec
folds = describe "folds" $ do
describe "ifoldr" $ do
specify "basic" $ do
ifoldr (\i x a -> if i*2==x then i:a else a) [] [0,2,5,6] `shouldBe` [0,1,3]
specify "empty" $ do
ifoldr undefined True [] `shouldBe` True
describe "ifoldl(')" $ do
specify "basic" $ do
ifoldl (\a i x -> if i*2==x then i:a else a) [] [0,2,5,6] `shouldBe` [3,1,0]
ifoldl' (\a i x -> if i*2==x then i:a else a) [] [0,2,5,6] `shouldBe` [3,1,0]
specify "empty" $ do
ifoldl undefined True [] `shouldBe` True
ifoldl' undefined True [] `shouldBe` True
describe "strictness" $ do
describe "acc" $ do
let f a i x = if i==1 then undefined else x:a
specify "lazy" $ do
evaluate (take 2 (ifoldl f [] [1..4::Int]))
`shouldReturn` [4,3]
specify "strict" $ do
evaluate (take 2 (ifoldl' f [] [1..4::Int]))
`shouldThrow` errorCall "Prelude.undefined"
describe "elem" $ do
let f a i _ = a+i
specify "lazy" $ do
evaluate (ifoldl f 1 [undefined, undefined, undefined])
`shouldReturn` 4
specify "strict" $ do
evaluate (ifoldl' f 1 [undefined, undefined, undefined])
`shouldReturn` 4
sublists :: Spec
sublists = describe "sublists" $ do
describe "ifilter" $ do
specify "all" $ do
ifilter (\i x -> i*2==x) [0,2,4,6] `shouldBe` [0,2,4,6]
specify "none" $ do
ifilter (\i x -> i*2/=x) [0,2,4,6] `shouldBe` []
specify "empty" $ do
ifilter undefined [] `shouldBe` ([] :: [Bool])
describe "itakeWhile" $ do
specify "all" $ do
itakeWhile (\i x -> i*2==x) [0,2,4,6] `shouldBe` [0,2,4,6]
specify "none" $ do
itakeWhile (\i x -> i*2/=x) [0,2,4,6] `shouldBe` []
specify "some" $ do
itakeWhile (\i x -> i*2==x) [0,2,5,6] `shouldBe` [0,2]
specify "empty" $ do
itakeWhile undefined [] `shouldBe` ([] :: [Bool])
describe "idropWhile" $ do
specify "all" $ do
idropWhile (\i x -> i*2==x) [0,2,4,6] `shouldBe` []
specify "none" $ do
idropWhile (\i x -> i*2/=x) [0,2,4,6] `shouldBe` [0,2,4,6]
specify "some" $ do
idropWhile (\i x -> i*2==x) [0,2,5,6] `shouldBe` [5,6]
specify "empty" $ do
idropWhile undefined [] `shouldBe` ([] :: [Bool])
search :: Spec
search = describe "search" $ do
describe "ifind" $ do
specify "found" $ do
ifind (\i x -> i*2==x) [1,3,4,7] `shouldBe` Just (2, 4)
specify "found twice" $ do
ifind (\i x -> i*2==x) [1,3,4,6] `shouldBe` Just (2, 4)
specify "not found" $ do
ifind (\i x -> i*2==x) [1,3,5,7] `shouldBe` Nothing
specify "empty" $ do
ifind undefined [] `shouldBe` (Nothing :: Maybe (Int, Bool))
describe "ifindIndex" $ do
specify "found" $ do
ifindIndex (\i x -> i*2==x) [1,3,4,7] `shouldBe` Just 2
specify "not found" $ do
ifindIndex (\i x -> i*2==x) [1,3,5,7] `shouldBe` Nothing
specify "empty" $ do
ifindIndex undefined [] `shouldBe` Nothing
describe "ifindIndices" $ do
specify "all" $ do
ifindIndices (\i x -> i*2==x) [0,2,4,6] `shouldBe` [0,1,2,3]
specify "none" $ do
ifindIndices (\i x -> i*2/=x) [0,2,4,6] `shouldBe` []
specify "empty" $ do
ifindIndices undefined [] `shouldBe` []
zipping :: Spec
zipping = describe "zipping" $ do
describe "basic" $ do
specify "2" $ do
izipWith (\i a b -> [i,a,b]) [1,2] [3,4] `shouldBe` [[0,1,3],[1,2,4]]
izipWith (\i a b -> [i,a,b]) [1,2] [3,4,0] `shouldBe` [[0,1,3],[1,2,4]]
izipWith (\i a b -> [i,a,b]) [1,2,0] [3,4] `shouldBe` [[0,1,3],[1,2,4]]
specify "3" $ do
izipWith3 (\i a b c -> [i,a,b,c]) [1,2] [3,4] [5,6]
`shouldBe` [[0,1,3,5],[1,2,4,6]]
izipWith3 (\i a b c -> [i,a,b,c]) [1,2] [3,4] [5,6,0]
`shouldBe` [[0,1,3,5],[1,2,4,6]]
izipWith3 (\i a b c -> [i,a,b,c]) [1,2] [3,4,0] [5,6]
`shouldBe` [[0,1,3,5],[1,2,4,6]]
izipWith3 (\i a b c -> [i,a,b,c]) [1,2,0] [3,4] [5,6]
`shouldBe` [[0,1,3,5],[1,2,4,6]]
describe "strictness" $ do
-- The point of this test is that zipWith should stop when it sees an
-- empty list, even if other lists are undefined
let u :: Bool
u = undefined
let su :: [Bool]
su = undefined
let em :: [Bool]
em = []
specify "2" $ do
izipWith undefined em su `shouldBe` em
specify "3" $ do
izipWith3 undefined em su su `shouldBe` em
izipWith3 undefined [u] em su `shouldBe` em
specify "4" $ do
izipWith4 undefined em su su su `shouldBe` em
izipWith4 undefined [u] em su su `shouldBe` em
izipWith4 undefined [u] [u] em su `shouldBe` em
buildingLists :: Spec
buildingLists = describe "building lists" $ do
describe "imapAccumR" $ do
specify "basic" $ do
imapAccumR (\a i x -> (2*a+i*x, x*2)) 0 [1,2,3]
`shouldBe` (2*(2*(2*0+3*2)+2*1)+1*0,[2,4,6])
specify "non-indexed" $ do
imapAccumR (\a _ x -> (2*a+x, 2*x+a)) 0 [1,2,3::Int]
`shouldBe`
mapAccumR (\a x -> (2*a+x, 2*x+a)) 0 [1,2,3]
specify "empty" $ do
imapAccumR undefined 0 [] `shouldBe` (0::Int,[]::[Bool])
describe "imapAccumL" $ do
specify "basic" $ do
imapAccumL (\a i x -> (2*a+i*x, x*2)) 0 [1,2,3]
`shouldBe` (2*(2*(2*0+1*0)+2*1)+3*2,[2,4,6])
specify "non-indexed" $ do
imapAccumL (\a _ x -> (2*a+x, 2*x+a)) 0 [1,2,3::Int]
`shouldBe`
mapAccumL (\a x -> (2*a+x, 2*x+a)) 0 [1,2,3]
specify "empty" $ do
imapAccumL undefined 0 [] `shouldBe` (0::Int,[]::[Bool])