{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
#if __GLASGOW_HASKELL__ >= 806
{-# LANGUAGE NoStarIsType #-}
#endif
module Data.NList
(
NList
, (<:>)
, (<++>)
, length
, head
, headMay
, tail
, tail'
, tailMay
, last
, lastMay
, init
, init'
, initMay
, toList
, take
, drop
, splitAt
, kth
, reverse
, intersperse
, transpose
, concat
, sort
, sortOn
, sortBy
, zip
, zipWith
, unzip
, replicate
, empty
, singleton
, mk1
, mk2
, mk3
, mk4
, mk5
, mk6
, mk7
, mk8
, mk9
, mk10
, Pred
) where
import qualified Data.List as List
import Data.Proxy (Proxy(..))
import GHC.TypeLits (KnownNat, Nat, natVal, type (+), type (-), type(*), type (<=))
import Prelude hiding (concat, drop, head, init, last, length, replicate, reverse, splitAt, tail, take, unzip, zip, zipWith)
infixr 5 <:>
infixr 5 <++>
newtype NList (n :: Nat) a = List [a] deriving (Eq, Ord)
empty :: NList 0 a
empty = List []
singleton :: a -> NList 1 a
singleton a = List [a]
(<:>) :: a -> NList n a -> NList (n + 1) a
(<:>) x (List xs) = List (x : xs)
(<++>) :: NList n a -> NList m a -> NList (n + m) a
(<++>) (List xs) (List ys) = List (xs List.++ ys)
length :: NList n a -> Int
length (List xs) = List.length xs
head :: (1 <= n) => NList n a -> a
head (List xs) = List.head xs
headMay :: NList n a -> Maybe a
headMay (List []) = Nothing
headMay (List (x:_)) = Just x
tail :: (1 <= n) => NList n a -> NList (Pred n) a
tail (List xs) = List (List.tail xs)
tail' :: NList n a -> NList (Pred n) a
tail' (List []) = List []
tail' (List (_:xs)) = List xs
tailMay :: NList n a -> Maybe (NList (Pred n) a)
tailMay (List []) = Nothing
tailMay (List (_:xs)) = Just (List xs)
last :: (1 <= n) => NList n a -> a
last (List xs) = List.last xs
lastMay :: NList n a -> Maybe a
lastMay (List []) = Nothing
lastMay (List xs) = Just (List.last xs)
init :: (1 <= n) => NList n a -> NList (Pred n) a
init (List xs) = List (List.init xs)
init' :: NList n a -> NList (Pred n) a
init' (List []) = List []
init' (List xs) = List (List.init xs)
initMay :: NList n a -> Maybe (NList (Pred n) a)
initMay (List []) = Nothing
initMay (List xs) = Just $ List (List.init xs)
take :: forall k n a. (KnownNat k, k <= n) => NList n a -> NList k a
take (List xs) = List (List.take k xs)
where
k = fromIntegral (natVal (Proxy :: Proxy k))
drop :: forall k n a. (KnownNat k, k <= n) => NList n a -> NList (n-k) a
drop (List xs) = List (List.drop k xs)
where
k = fromIntegral (natVal (Proxy :: Proxy k))
splitAt :: forall k n a. (KnownNat k, k <= n) => NList n a -> (NList k a, NList (n-k) a)
splitAt (List xs) = let (ys, zs) = List.splitAt k xs in (List ys, List zs)
where
k = fromIntegral (natVal (Proxy :: Proxy k))
reverse :: NList n a -> NList n a
reverse (List xs) = List (List.reverse xs)
intersperse :: a -> NList n a -> NList (Pred (n * 2)) a
intersperse x (List xs) = List (List.intersperse x xs)
transpose :: NList n (NList m a) -> NList m (NList n a)
transpose (List xss) = List . fmap List $ List.transpose (fmap toList xss)
kth :: forall k n a. (KnownNat k, k <= n-1) => NList n a -> a
kth (List xs) = xs List.!! fromIntegral (natVal (Proxy :: Proxy k))
sort :: Ord a => NList n a -> NList n a
sort (List xs) = List (List.sort xs)
sortOn :: Ord b => (a -> b) -> NList n a -> NList n a
sortOn f (List xs) = List (List.sortOn f xs)
sortBy :: (a -> a -> Ordering) -> NList n a -> NList n a
sortBy f (List xs) = List (List.sortBy f xs)
toList :: NList n a -> [a]
toList (List xs) = xs
zip :: NList n a -> NList n b -> NList n (a, b)
zip (List xs) (List ys) = List (xs `List.zip` ys)
zipWith :: (a -> b -> c) -> NList n a -> NList n b -> NList n c
zipWith f (List xs) (List ys) = List (List.zipWith f xs ys)
unzip :: NList n (a, b) -> (NList n a, NList n b)
unzip (List xs) = (List ys, List zs)
where
(ys, zs) = List.unzip xs
concat :: NList n (NList m a) -> NList (n * m) a
concat (List xss) = List (List.concatMap toList xss)
replicate ::forall n a. KnownNat n => a -> NList n a
replicate = List . List.replicate n
where
n = fromIntegral $ natVal (Proxy :: Proxy n)
mk1 :: a -> NList 1 a
mk1 = singleton
mk2 :: a -> a -> NList 2 a
mk2 a1 a2 = List [a1, a2]
mk3 :: a -> a -> a -> NList 3 a
mk3 a1 a2 a3 = List [a1, a2, a3]
mk4 :: a -> a -> a -> a -> NList 4 a
mk4 a1 a2 a3 a4 = List [a1, a2, a3, a4]
mk5 :: a -> a -> a -> a -> a -> NList 5 a
mk5 a1 a2 a3 a4 a5 = List [a1, a2, a3, a4, a5]
mk6 :: a -> a -> a -> a -> a -> a -> NList 6 a
mk6 a1 a2 a3 a4 a5 a6 = List [a1, a2, a3, a4, a5, a6]
mk7 :: a -> a -> a -> a -> a -> a -> a -> NList 7 a
mk7 a1 a2 a3 a4 a5 a6 a7 = List [a1, a2, a3, a4, a5, a6, a7]
mk8 :: a -> a -> a -> a -> a -> a -> a -> a -> NList 8 a
mk8 a1 a2 a3 a4 a5 a6 a7 a8 = List [a1, a2, a3, a4, a5, a6, a7, a8]
mk9 :: a -> a -> a -> a -> a -> a -> a -> a -> a -> NList 9 a
mk9 a1 a2 a3 a4 a5 a6 a7 a8 a9 = List [a1, a2, a3, a4, a5, a6, a7, a8, a9]
mk10 :: a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> NList 10 a
mk10 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 = List [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10]
instance (KnownNat n, Show a) => Show (NList n a) where
showsPrec p (List xs) = showParen (p > 10) $
showString "List " . shows (natVal (Proxy :: Proxy n)) . showString " " . shows xs
instance Functor (NList n) where
fmap f (List xs) = List (List.map f xs)
instance KnownNat n => Applicative (NList n) where
pure = replicate
(<*>) = zipWith ($)
instance Foldable (NList n) where
foldr f z (List xs) = List.foldr f z xs
instance Traversable (NList n) where
sequenceA (List xs) = List <$> sequenceA xs
type family Pred (n :: Nat) :: Nat where
Pred 0 = 0
Pred n = (n-1)