{-# LANGUAGE RankNTypes #-} module Main (main) where import Data.List qualified as List import Data.List.NonEmpty (NonEmpty(..)) import Data.List.NonEmpty qualified as NEL -- The inits implementation added in 7.10 uses a queue rotated around -- powers of 2, starting the rotation only at size 255, so we want to check -- around powers of 2 and around the switch. ranges :: [Int] ranges = [1..20] ++ [252..259] ++ [508..515] nonEmptyUpTo :: Int -> NonEmpty Int nonEmptyUpTo n | n >= 1 = NEL.fromList [1..n] nonEmptyUpTo n = error $ "nonEmptyUpTo: invalid argument: " ++ show n simple :: (forall a . NonEmpty a -> [[a]]) -> [[[Int]]] simple impl = [impl (nonEmptyUpTo n) | n <- ranges] nonEmptyInits1 :: NonEmpty a -> [[a]] nonEmptyInits1 = map NEL.toList . NEL.toList . NEL.inits1 -- inits1 should be the same as inits on nonempty lists, except that the first -- element should not be included alternativeInits1 :: NonEmpty a -> [[a]] alternativeInits1 = tail . List.inits . NEL.toList nonEmptyTails1 :: NonEmpty a -> [[a]] nonEmptyTails1 = map NEL.toList . NEL.toList . NEL.tails1 -- tails1 should be the same as tails on nonempty lists, except that the last -- element should not be included alternativeTails1 :: NonEmpty a -> [[a]] alternativeTails1 = init . List.tails . NEL.toList -- We want inits1 (xs <> undefined) = inits1 xs <> undefined -- (there's no similar property for tails1 because that function starts with the -- longest suffix) lazinessInits1 :: Bool lazinessInits1 = [take n (nonEmptyInits1 (nonEmptyUpTo n <> undefined)) | n <- ranges] == simple nonEmptyInits1 main :: IO () main | simple nonEmptyInits1 /= simple alternativeInits1 = error "inits1 failed simple test" | simple nonEmptyTails1 /= simple alternativeTails1 = error "tails1 failed simple test" | not lazinessInits1 = error "inits1 failed laziness test" | otherwise = return ()