    -----------------------------------------------------------------------------
    -- |
    -- Module      :  Data.Singletons.Prelude.List.Internal.Disambiguation
    -- Copyright   :  (C) 2016 Richard Eisenberg
    -- License     :  BSD-style (see LICENSE)
    -- Maintainer  :  Ryan Scott
    -- Stability   :  experimental
    -- Portability :  non-portable
    --
    -- Renames a bunch of List functions because singletons can't support qualified
    -- names. :(
    --
    ----------------------------------------------------------------------------

    {-# LANGUAGE TemplateHaskell, ScopedTypeVariables, TypeFamilies,
                 UndecidableInstances, GADTs, DataKinds, PolyKinds #-}
    {-# OPTIONS_GHC -Wno-missing-signatures #-}

    module Data.Singletons.Prelude.List.Internal.Disambiguation where

    import Data.Singletons.Single
    import Data.Singletons.Prelude.Base
    import Data.Singletons.Prelude.Instances
    import Data.Singletons.Prelude.List.Internal
    import Data.Singletons.Prelude.Num
    import Data.Singletons.Prelude.Ord
    import Data.Singletons.Prelude.Eq
    import Data.List
    import GHC.TypeLits

    -- singletons doesn't support qualified names :(
    $(singletons [d|
      listlast :: [a] -> a
      listlast = last

      listinit :: [a] -> [a]
      listinit = init

      listsort :: Ord a => [a] -> [a]
      listsort = sort

      listinits :: [a] -> [[a]]
      listinits = inits

      listtails :: [a] -> [[a]]
      listtails = tails

      listinsert :: Ord a => a -> [a] -> [a]
      listinsert = insert

      listscanl :: (b -> a -> b) -> b -> [a] -> [b]
      listscanl = scanl

      listscanr :: (a -> b -> b) -> b -> [a] -> [b]
      listscanr = scanr

      listscanr1 :: (a -> a -> a) -> [a] -> [a]
      listscanr1 = scanr1

      listintersperse :: a -> [a] -> [a]
      listintersperse = intersperse

      listreverse :: [a] -> [a]
      listreverse = reverse

      listtakeWhile :: (a -> Bool) -> [a] -> [a]
      listtakeWhile = takeWhile

      listdropWhile :: (a -> Bool) -> [a] -> [a]
      listdropWhile = dropWhile

      listspan :: (a -> Bool) -> [a] -> ([a], [a])
      listspan = span

      listfilter :: (a -> Bool) -> [a] -> [a]
      listfilter = filter

      listpartition :: (a -> Bool) -> [a] -> ([a], [a])
      listpartition = partition

      listsortBy :: (a -> a -> Ordering) -> [a] -> [a]
      listsortBy = sortBy

      listisPrefixOf :: Eq a => [a] -> [a] -> Bool
      listisPrefixOf = isPrefixOf

      listzip :: [a] -> [b] -> [(a, b)]
      listzip = zip

      listzipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
      listzipWith = zipWith

      listnubBy :: (a -> a -> Bool) -> [a] -> [a]
      listnubBy = nubBy

      listtranspose :: [[a]] -> [[a]]
      listtranspose = transpose

      listunzip :: [(a,b)] -> ([a],[b])
      listunzip = unzip

      listmap :: (a -> b) -> [a] -> [b]
      listmap = map

      listelem :: Eq a => a -> [a] -> Bool
      listelem = elem

      listfoldl :: (b -> a -> b) -> b -> [a] -> b
      listfoldl = foldl

      listfoldl' :: (b -> a -> b) -> b -> [a] -> b
      listfoldl' = foldl'

      listfoldl1 :: (a -> a -> a) -> [a] -> a
      listfoldl1 = foldl1

      listfoldr :: (a -> b -> b) -> b -> [a] -> b
      listfoldr = foldr

      listfoldr1 :: (a -> a -> a) -> [a] -> a
      listfoldr1 = foldr1

      listmaximum :: Ord a => [a] -> a
      listmaximum = maximum

      listminimum :: Ord a => [a] -> a
      listminimum = minimum

      listnull :: [a] -> Bool
      listnull = null

      listproduct :: Num a => [a] -> a
      listproduct = product

      listsum :: Num a => [a] -> a
      listsum = sum
      |])

    $(singletonsOnly [d|
      listtake :: Nat -> [a] -> [a]
      listtake = take

      listdrop :: Nat -> [a] -> [a]
      listdrop = drop

      listsplitAt :: Nat -> [a] -> ([a], [a])
      listsplitAt = splitAt

      listindex :: [a] -> Nat -> a
      listindex = (!!)

      listlength :: [a] -> Nat
      listlength = length
      |])

    listtake :: Nat -> [a] -> [a]
    listtake = undefined

    listdrop :: Nat -> [a] -> [a]
    listdrop = undefined

    listsplitAt :: Nat -> [a] -> ([a], [a])
    listsplitAt = undefined

    listindex :: [a] -> Nat -> a
    listindex = undefined

    listlength :: [a] -> Nat
    listlength = undefined