text: -----------------------------------------------------------------------------
  -- |
  -- Module      :  Data.List
  -- Copyright   :  (c) 2020 EMQ Technologies Co., Ltd.
  -- License     :  BSD-style (see the LICENSE file)
  --
  -- Maintainer  :  Feng Lee, feng@emqx.io
  --                Yang M, yangm@emqx.io
  -- Stability   :  experimental
  -- Portability :  portable
  --
  -- The List datatype.
  --
  -----------------------------------------------------------------------------
  module Data.List where
  
  import Data.Maybe (Maybe)
  import Foreign (ffi1, ffi2, ffi3)
  
  -----------------------------------------------------------------------------
  -- Basic functions
  -----------------------------------------------------------------------------
  
  infixl 6 append as ++
  
  append :: forall a. [a] -> [a] -> [a]
  append = ffi2 :lists :append
  
  -- infixr 6 cons as :
  
  -- | Cons a list.
  foreign import cons :: forall a. a -> [a] -> [a]
  
  -- | Return the first element of a list.
  foreign import head :: forall a. [a] -> a
  
  -- | Return the last element of a list.
  last :: forall a. [a] -> a
  last = ffi1 :lists :last
  
  -- | Return the elements after the head of a list.
  foreign import tail :: forall a. [a] -> [a]
  
  foreign import init :: forall a. [a] -> [a]
  
  -- | Decompose a list into its head and tail.
  foreign import uncons :: forall a. [a] -> Maybe (a, [a])
  
  -- | Return the length/size of the list.
  length :: forall a. [a] -> Integer
  length = ffi1 :erlang :length
  
  -- | Reverse the list.
  reverse :: forall a. [a] -> [a]
  reverse = ffi1 :lists :reverse
  
  -- | Concat
  concat :: forall a. [[a]] -> [a]
  concat = ffi1 :lists :concat
  
  filter :: forall a. (a -> Boolean) -> [a] -> [a]
  filter = ffi2 :lists :filter
  
  replicate :: forall a. Integer -> a -> [a]
  replicate = ffi2 :lists :duplicate
  
  -----------------------------------------------------------------------------
  -- Build lists
  -----------------------------------------------------------------------------
  
  -- foreign import scanl :: forall a b. (b -> a -> b) -> b -> [a] -> [b]
  
  -- foreign import scanr :: forall a b. (a -> b -> b) -> b -> [a] -> [b]
  
  -----------------------------------------------------------------------------
  -- Split and Sublists
  -----------------------------------------------------------------------------
  
  foreign import take :: forall a. Integer -> [a] -> [a]
  
  takeWhile :: forall a. (a -> Boolean) -> [a] -> [a]
  takeWhile = ffi2 :lists :takeWhile
  
  foreign import drop :: forall a. Integer -> [a] -> [a]
  
  -- | Extract a sublist by a start and end index.
  foreign import slice :: forall a. Integer -> Integer -> [a] -> [a]
  
  -- | An alias for `splitWith` function.
  span :: forall a. (a -> Boolean) -> [a] -> ([a], [a])
  span = splitWith
  
  -- | Split List into two lists according to Pred.
  splitWith :: forall a. (a -> Boolean) -> [a] -> ([a], [a])
  splitWith = ffi2 :lists :splitwith
  
  splitAt :: forall a. Integer -> [a] -> ([a], [a])
  splitAt = ffi2 :lists :split
  
  dropWhile :: forall a. (a -> Boolean) -> [a] -> [a]
  dropWhile = ffi2 :lists :dropWhile
  
  -----------------------------------------------------------------------------
  -- Sort lists
  -----------------------------------------------------------------------------
  
  sort :: forall a. [a] -> [a]
  sort = ffi1 :lists :sort
  
  keysort :: forall a b. Integer -> [(a, b)] -> [(a, b)]
  keysort = ffi2 :lists :keysort
  
  usort :: forall a. [a] -> [a]
  usort = ffi1 :lists :usort
  
  ukeysort :: forall a b. Integer -> [(a, b)] -> [(a, b)]
  ukeysort = ffi2 :lists :ukeysort
  
  -----------------------------------------------------------------------------
  -- Zip and unzip lists
  -----------------------------------------------------------------------------
  
  zip :: forall a b. [a] -> [b] -> [(a, b)]
  zip = ffi2 :lists :zip
  
  zip3 :: forall a b c. [a] -> [b] -> [c] -> [(a, b, c)]
  zip3 = ffi3 :lists :zip3
  
  foreign import zipWith :: forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
  
  foreign import zipWith3 :: forall a b c d. (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]
  
  unzip :: forall a b. [(a, b)] -> ([a], [b])
  unzip = ffi1 :lists :unzip
  
  unzip3 :: forall a b c. [(a, b, c)] -> ([a], [b], [c])
  unzip3 = ffi1 :lists :unzip3
  
  member :: forall a. a -> [a] -> Boolean
  member = ffi2 :lists :member
  