Skip to content

Commit

Permalink
0.1.0.1
Browse files Browse the repository at this point in the history
  • Loading branch information
zliu41 committed Feb 20, 2020
1 parent c649363 commit bed627b
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 1 deletion.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,7 @@
## 0.1.0.0 -- 2020-02-18

* Initial release.

## 0.1.0.1 -- 2020-02-19

* Add `ToTuple`, `FromTuple` and `uncons`.
2 changes: 1 addition & 1 deletion indexed-containers.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ cabal-version: 2.4
-- http://haskell.org/cabal/users-guide/

name: indexed-containers
version: 0.1.0.0
version: 0.1.0.1
synopsis: Simple, no-frills indexed lists.
description: If the lengths of your lists are known statically, using indexed lists improves type safety with no runtime overhead.
category: Data Structures
Expand Down
117 changes: 117 additions & 0 deletions src/Data/NList.hs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
Expand All @@ -10,6 +11,8 @@
{-# LANGUAGE NoStarIsType #-}
#endif

{-# OPTIONS_GHC -fno-warn-incomplete-patterns #-}

-----------------------------------------------------------------------------
-- |
-- Module : Data.NList
Expand Down Expand Up @@ -40,6 +43,7 @@ module Data.NList
, init
, init'
, initMay
, uncons
, toList

-- * Extracing sublists
Expand Down Expand Up @@ -81,6 +85,10 @@ module Data.NList
, mk9
, mk10

-- * To and from tuples
, FromTuple(..)
, ToTuple(..)

-- * Predecessor of a Nat
, Pred
) where
Expand Down Expand Up @@ -210,6 +218,13 @@ initMay :: NList n a -> Maybe (NList (Pred n) a)
initMay (List []) = Nothing
initMay (List xs) = Just $ List (List.init xs)

-- | Decompose a list into head and tail.
--
-- > uncons (singleton 'a') === ('a', empty)
-- > uncons (mk3 'a' 'b' 'c') === ('a', mk2 'b' 'c')
uncons :: (1 <= n) => NList n a -> (a, NList (n-1) a)
uncons (List (x:xs)) = (x, List xs)

-- | Return the first @k@ elements of a list whose length is at least @k@.
--
-- > take @0 (mk3 'a' 'b' 'c') === empty
Expand Down Expand Up @@ -378,6 +393,108 @@ 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]


-- | Typeclass for converting tuples to 'NList's.
class FromTuple a where
type List a
fromTuple :: a -> List a

instance FromTuple (a, a) where
type List (a, a) = NList 2 a
-- > fromTuple ('a', 'b') === mk2 'a' 'b'
fromTuple (a1, a2) = mk2 a1 a2

instance FromTuple (a, a, a) where
type List (a, a, a) = NList 3 a
-- > fromTuple ('a', 'b', 'c') === mk3 'a' 'b' 'c'
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 ('a', 'b', 'c', 'd') === mk4 'a' 'b' 'c' 'd'
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 ('a', 'b', 'c', 'd', 'e') === mk5 'a' 'b' 'c' 'd' 'e'
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 ('a', 'b', 'c', 'd', 'e', 'f') === mk6 'a' 'b' 'c' 'd' 'e' 'f'
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 ('a', 'b', 'c', 'd', 'e', 'f', 'g') === mk7 'a' 'b' 'c' 'd' 'e' 'f' 'g'
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 ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h') === mk8 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h'
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 ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i') === mk9 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i'
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 ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j') === mk10 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j'
fromTuple (a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) = mk10 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10


-- | Typeclass for converting 'NList's to tuples.
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 (mk2 'a' 'b') === ('a', 'b')
toTuple (List [a1, a2]) = (a1, a2)

instance ToTuple (NList 3 a) where
type Tuple (NList 3 a) = (a, a, a)
-- > toTuple (mk3 'a' 'b' 'c') === ('a', 'b', 'c')
toTuple (List [a1, a2, a3]) = (a1, a2, a3)

instance ToTuple (NList 4 a) where
type Tuple (NList 4 a) = (a, a, a, a)
-- > toTuple (mk4 'a' 'b' 'c' 'd') === ('a', 'b', 'c', 'd')
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 (mk5 'a' 'b' 'c' 'd' 'e') === ('a', 'b', 'c', 'd', 'e')
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 (mk6 'a' 'b' 'c' 'd' 'e' 'f') === ('a', 'b', 'c', 'd', 'e', 'f')
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 (mk7 'a' 'b' 'c' 'd' 'e' 'f' 'g') === ('a', 'b', 'c', 'd', 'e', 'f', 'g')
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 (mk8 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h') === ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h')
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 (mk9 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i') === ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i')
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 (mk10 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j') === ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j')
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
Expand Down
20 changes: 20 additions & 0 deletions test/hspec/Data/NListSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ spec = do
initMay (empty :: NList 0 ()) === Nothing
initMay (singleton 'a') === Just empty
initMay (mk3 'a' 'b' 'c') === Just (mk2 'a' 'b')
uncons (singleton 'a') === ('a', empty)
uncons (mk3 'a' 'b' 'c') === ('a', mk2 'b' 'c')
take @0 (mk3 'a' 'b' 'c') === empty
take @2 (mk3 'a' 'b' 'c') === mk2 'a' 'b'
take @3 (mk3 'a' 'b' 'c') === mk3 'a' 'b' 'c'
Expand Down Expand Up @@ -80,3 +82,21 @@ spec = do
toList (mk8 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h') === "abcdefgh"
toList (mk9 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i') === "abcdefghi"
toList (mk10 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j') === "abcdefghij"
fromTuple ('a', 'b') === mk2 'a' 'b'
fromTuple ('a', 'b', 'c') === mk3 'a' 'b' 'c'
fromTuple ('a', 'b', 'c', 'd') === mk4 'a' 'b' 'c' 'd'
fromTuple ('a', 'b', 'c', 'd', 'e') === mk5 'a' 'b' 'c' 'd' 'e'
fromTuple ('a', 'b', 'c', 'd', 'e', 'f') === mk6 'a' 'b' 'c' 'd' 'e' 'f'
fromTuple ('a', 'b', 'c', 'd', 'e', 'f', 'g') === mk7 'a' 'b' 'c' 'd' 'e' 'f' 'g'
fromTuple ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h') === mk8 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h'
fromTuple ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i') === mk9 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i'
fromTuple ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j') === mk10 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j'
toTuple (mk2 'a' 'b') === ('a', 'b')
toTuple (mk3 'a' 'b' 'c') === ('a', 'b', 'c')
toTuple (mk4 'a' 'b' 'c' 'd') === ('a', 'b', 'c', 'd')
toTuple (mk5 'a' 'b' 'c' 'd' 'e') === ('a', 'b', 'c', 'd', 'e')
toTuple (mk6 'a' 'b' 'c' 'd' 'e' 'f') === ('a', 'b', 'c', 'd', 'e', 'f')
toTuple (mk7 'a' 'b' 'c' 'd' 'e' 'f' 'g') === ('a', 'b', 'c', 'd', 'e', 'f', 'g')
toTuple (mk8 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h') === ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h')
toTuple (mk9 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i') === ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i')
toTuple (mk10 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j') === ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j')

0 comments on commit bed627b

Please sign in to comment.