ranged-list-0.1.1.1: src/Data/List/Length.hs
{-# LANGUAGE BlockArguments, TupleSections #-}
{-# LANGUAGE DataKinds, TypeOperators #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE FlexibleContexts #-}
{-# OPTIONS_GHC -Wall -fno-warn-tabs #-}
module Data.List.Length (
-- * LENGTHED LIST LEFT
-- ** Type
LengthL, RangeL(NilL, (:.)),
-- ** AddL
AddL, (++.),
-- ** Unfoldr
-- *** class
Unfoldr,
-- *** without monad
repeatL, fillL, unfoldr, unfoldrWithBase,
-- *** with monad
unfoldrM, unfoldrMWithBase,
-- ** ZipL
ZipL, zipL, zipWithL, zipWithML,
-- ** ListToLengthL
ListToLengthL, splitL, chunksL, chunksL',
-- * LENGTHED LIST RIGHT
-- ** Type
LengthR, RangeR(NilR, (:+)),
-- ** AddR
AddR, (+++),
-- ** Unfoldl
-- *** class
Unfoldl,
-- *** without monad
repeatR, fillR, unfoldl, unfoldlWithBase,
-- *** with monad
unfoldlM, unfoldlMWithBase,
-- ** ZipR
ZipR, zipR, zipWithR, zipWithMR,
-- ** ListToLengthR
ListToLengthR, listToLengthR, chunksR, chunksR',
-- * LEFT TO RIGHT
LeftToRight, (++.+), leftToRight,
-- * RIGHT TO LEFT
RightToLeft, (++..), rightToLeft ) where
import Control.Arrow (first, (***))
import Data.List.Range (
RangeL(..), AddL, (++.), LoosenLMax, loosenLMax, Unfoldr,
ZipL, zipL, zipWithL, zipWithML,
RangeR(..), AddR, (+++), LoosenRMax, loosenRMax, Unfoldl,
ZipR, zipR, zipWithR, zipWithMR,
LeftToRight, (++.+), leftToRight, RightToLeft, (++..), rightToLeft )
import Data.List.Length.LengthL (
LengthL, unfoldr, unfoldrWithBase, unfoldrM, unfoldrMWithBase,
ListToLengthL, splitL )
import Data.List.Length.LengthR (
LengthR, unfoldl, unfoldlWithBase, unfoldlM, unfoldlMWithBase,
ListToLengthR, listToLengthR )
import GHC.TypeNats
---------------------------------------------------------------------------
-- LENGTH LEFT
-- LENGTH RIGHT
---------------------------------------------------------------------------
-- LENGTH LEFT
---------------------------------------------------------------------------
repeatL :: (0 <= n, Unfoldr 0 n n) => a -> LengthL n a
repeatL = fillL NilL
{-^
To repeat a value of type @a@ to construct a list of type @LengthL n a@.
>>> :set -XDataKinds
>>> repeatL 'c' :: LengthL 5 Char
'c' :. ('c' :. ('c' :. ('c' :. ('c' :. NilL))))
-}
fillL :: Unfoldr n m m => RangeL n m a -> a -> LengthL m a
fillL = (`unfoldrWithBase` \x -> (x, x))
{-^
To fill a list of type @LengthL n a@ with a value of type @a@.
>>> :set -XDataKinds
>>> fillL ('a' :. 'b' :.. NilL) 'c' :: LengthL 5 Char
'a' :. ('b' :. ('c' :. ('c' :. ('c' :. NilL))))
-}
chunksL :: ListToLengthL n => [a] -> ([LengthL n a], RangeL 0 (n - 1) a)
chunksL = either ([] ,) (uncurry first . ((:) *** chunksL)) . splitL
{-^
To separate a list to multiple lengthed lists.
It return separeted lengthed lists and a not enough length fragment.
>>> :set -XTypeApplications -XDataKinds
>>> chunksL @3 "foo bar"
(['f' :. ('o' :. ('o' :. NilL)),' ' :. ('b' :. ('a' :. NilL))],'r' :.. NilL)
-}
chunksL' :: (Unfoldr 0 n n, LoosenLMax 0 (n - 1) n, ListToLengthL n) =>
a -> [a] -> [LengthL n a]
chunksL' z xs = case chunksL xs of
(cs, NilL) -> cs; (cs, rs) -> cs ++ [loosenLMax rs `fillL` z]
{-^
It is like chunksL.
But if there is a not enough length fragment, then it fill with a default value.
>>> :set -XTypeApplications -XDataKinds
>>> print `mapM_` chunksL' @3 '@' "foo bar"
'f' :. ('o' :. ('o' :. NilL))
' ' :. ('b' :. ('a' :. NilL))
'r' :. ('@' :. ('@' :. NilL))
-}
---------------------------------------------------------------------------
-- LENGTH RIGHT
---------------------------------------------------------------------------
repeatR :: (0 <= n, Unfoldl 0 n n) => a -> LengthR n a
repeatR = (`fillR` NilR)
{-^
To repeat a value of type @a@ to construct a list of type @LengthR n a@.
>>> :set -XDataKinds
>>> repeatR 'c' :: LengthR 5 Char
((((NilR :+ 'c') :+ 'c') :+ 'c') :+ 'c') :+ 'c'
-}
fillR :: Unfoldl n m m => a -> RangeR n m a -> LengthR m a
fillR = unfoldlWithBase \x -> (x, x)
{-^
To fill a list of type @LengthR n a@ with a default value.
>>> :set -XDataKinds
>>> fillR 'c' (NilR :++ 'a' :+ 'b') :: LengthR 5 Char
((((NilR :+ 'c') :+ 'c') :+ 'c') :+ 'a') :+ 'b'
-}
chunksR :: ListToLengthR n => [a] -> ([LengthR n a], RangeR 0 (n - 1) a)
chunksR = either ([] ,) (uncurry first . ((:) *** chunksR)) . listToLengthR
{-^
To separate a list to multiple lengthed lists.
It return separated lengthed lists and a not enough length fragment.
>>> :set -XTypeApplications -XDataKinds
>>> chunksR @3 "foo bar"
([((NilR :+ 'o') :+ 'o') :+ 'f',((NilR :+ 'a') :+ 'b') :+ ' '],NilR :++ 'r')
-}
chunksR' :: (Unfoldl 0 n n, LoosenRMax 0 (n - 1) n, ListToLengthR n) =>
a -> [a] -> [LengthR n a]
chunksR' z xs = case chunksR xs of
(cs, NilR) -> cs; (cs, rs) -> cs ++ [z `fillR` loosenRMax rs]
{-^
It is like @chunksR@.
But if there is a not enough length fragment, then it fill with a default value.
>>> :set -XTypeApplications -XDataKinds
>>> print `mapM_` chunksR' @3 '@' "foo bar"
((NilR :+ 'o') :+ 'o') :+ 'f'
((NilR :+ 'a') :+ 'b') :+ ' '
((NilR :+ '@') :+ '@') :+ 'r'
-}