{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
#if __GLASGOW_HASKELL__ >= 806
{-# LANGUAGE NoStarIsType #-}
#endif
{-# OPTIONS_GHC -fno-warn-incomplete-patterns #-}
module Data.NList
(
NList
, (<:>)
, (<++>)
, length
, head
, headMay
, tail
, tail'
, tailMay
, last
, lastMay
, init
, init'
, initMay
, uncons
, 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
, FromTuple(..)
, ToTuple(..)
, 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)
uncons :: (1 <= n) => NList n a -> (a, NList (n-1) a)
uncons (List (x:xs)) = (x, List 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]
class FromTuple a where
type List a
fromTuple :: a -> List a
instance FromTuple (a, a) where
type List (a, a) = NList 2 a
fromTuple (a1, a2) = mk2 a1 a2
instance FromTuple (a, a, a) where
type List (a, a, a) = NList 3 a
fromTuple (a1, a2, a3) = mk3 a1 a2 a3
instance FromTuple (a, a, a, a) where
type List (a, a, a, a) = NList 4 a
fromTuple (a1, a2, a3, a4) = mk4 a1 a2 a3 a4
instance FromTuple (a, a, a, a, a) where
type List (a, a, a, a, a) = NList 5 a
fromTuple (a1, a2, a3, a4, a5) = mk5 a1 a2 a3 a4 a5
instance FromTuple (a, a, a, a, a, a) where
type List (a, a, a, a, a, a) = NList 6 a
fromTuple (a1, a2, a3, a4, a5, a6) = mk6 a1 a2 a3 a4 a5 a6
instance FromTuple (a, a, a, a, a, a, a) where
type List (a, a, a, a, a, a, a) = NList 7 a
fromTuple (a1, a2, a3, a4, a5, a6, a7) = mk7 a1 a2 a3 a4 a5 a6 a7
instance FromTuple (a, a, a, a, a, a, a, a) where
type List (a, a, a, a, a, a, a, a) = NList 8 a
fromTuple (a1, a2, a3, a4, a5, a6, a7, a8) = mk8 a1 a2 a3 a4 a5 a6 a7 a8
instance FromTuple (a, a, a, a, a, a, a, a, a) where
type List (a, a, a, a, a, a, a, a, a) = NList 9 a
fromTuple (a1, a2, a3, a4, a5, a6, a7, a8, a9) = mk9 a1 a2 a3 a4 a5 a6 a7 a8 a9
instance FromTuple (a, a, a, a, a, a, a, a, a, a) where
type List (a, a, a, a, a, a, a, a, a, a) = NList 10 a
fromTuple (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) = mk10 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10
class ToTuple a where
type Tuple a
toTuple :: a -> Tuple a
instance ToTuple (NList 2 a) where
type Tuple (NList 2 a) = (a, a)
toTuple (List [a1, a2]) = (a1, a2)
instance ToTuple (NList 3 a) where
type Tuple (NList 3 a) = (a, a, a)
toTuple (List [a1, a2, a3]) = (a1, a2, a3)
instance ToTuple (NList 4 a) where
type Tuple (NList 4 a) = (a, a, a, a)
toTuple (List [a1, a2, a3, a4]) = (a1, a2, a3, a4)
instance ToTuple (NList 5 a) where
type Tuple (NList 5 a) = (a, a, a, a, a)
toTuple (List [a1, a2, a3, a4, a5]) = (a1, a2, a3, a4, a5)
instance ToTuple (NList 6 a) where
type Tuple (NList 6 a) = (a, a, a, a, a, a)
toTuple (List [a1, a2, a3, a4, a5, a6]) = (a1, a2, a3, a4, a5, a6)
instance ToTuple (NList 7 a) where
type Tuple (NList 7 a) = (a, a, a, a, a, a, a)
toTuple (List [a1, a2, a3, a4, a5, a6, a7]) = (a1, a2, a3, a4, a5, a6, a7)
instance ToTuple (NList 8 a) where
type Tuple (NList 8 a) = (a, a, a, a, a, a, a, a)
toTuple (List [a1, a2, a3, a4, a5, a6, a7, a8]) = (a1, a2, a3, a4, a5, a6, a7, a8)
instance ToTuple (NList 9 a) where
type Tuple (NList 9 a) = (a, a, a, a, a, a, a, a, a)
toTuple (List [a1, a2, a3, a4, a5, a6, a7, a8, a9]) = (a1, a2, a3, a4, a5, a6, a7, a8, a9)
instance ToTuple (NList 10 a) where
type Tuple (NList 10 a) = (a, a, a, a, a, a, a, a, a, a)
toTuple (List [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10]) = (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)