{-# LANGUAGE FlexibleInstances     #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies          #-}

module HaskellWorks.Data.Unsnoc
    ( Container(..)
    , Unsnoc(..)
    ) where

import Data.Int
import Data.Maybe
import Data.Word
import HaskellWorks.Data.Container
import Prelude                     hiding (drop)

import qualified Data.ByteString      as BS
import qualified Data.Vector          as DV
import qualified Data.Vector.Storable as DVS

class Unsnoc v where
  unsnoc :: v -> Maybe (Elem v, v)

instance Unsnoc String where
  unsnoc :: String -> Maybe (Elem String, String)
unsnoc String
s = case String -> String
forall a. [a] -> [a]
reverse String
s of
    (Char
x:String
xs) -> (Char, String) -> Maybe (Char, String)
forall a. a -> Maybe a
Just (Char
x, String -> String
forall a. [a] -> [a]
reverse String
xs)
    String
_      -> Maybe (Elem String, String)
forall a. Maybe a
Nothing
  {-# INLINE unsnoc   #-}

instance Unsnoc BS.ByteString where
  unsnoc :: ByteString -> Maybe (Elem ByteString, ByteString)
unsnoc ByteString
s = if ByteString -> Int
BS.length ByteString
s Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 then Maybe (Elem ByteString, ByteString)
forall a. Maybe a
Nothing else (Word8, ByteString) -> Maybe (Word8, ByteString)
forall a. a -> Maybe a
Just (ByteString -> Word8
BS.last ByteString
s, Int -> ByteString -> ByteString
BS.take (ByteString -> Int
BS.length ByteString
s Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) ByteString
s)
  {-# INLINE unsnoc   #-}

instance Unsnoc (DV.Vector Word8) where
  unsnoc :: Vector Word8 -> Maybe (Elem (Vector Word8), Vector Word8)
unsnoc Vector Word8
s = if Vector Word8 -> Int
forall a. Vector a -> Int
DV.length Vector Word8
s Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 then Maybe (Elem (Vector Word8), Vector Word8)
forall a. Maybe a
Nothing else (Word8, Vector Word8) -> Maybe (Word8, Vector Word8)
forall a. a -> Maybe a
Just (Vector Word8 -> Word8
forall a. Vector a -> a
DV.last Vector Word8
s, Int -> Vector Word8 -> Vector Word8
forall a. Int -> Vector a -> Vector a
DV.take (Vector Word8 -> Int
forall a. Vector a -> Int
DV.length Vector Word8
s Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Vector Word8
s)
  {-# INLINE unsnoc   #-}

instance Unsnoc (DV.Vector Word16) where
  unsnoc :: Vector Word16 -> Maybe (Elem (Vector Word16), Vector Word16)
unsnoc Vector Word16
s = if Vector Word16 -> Int
forall a. Vector a -> Int
DV.length Vector Word16
s Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 then Maybe (Elem (Vector Word16), Vector Word16)
forall a. Maybe a
Nothing else (Word16, Vector Word16) -> Maybe (Word16, Vector Word16)
forall a. a -> Maybe a
Just (Vector Word16 -> Word16
forall a. Vector a -> a
DV.last Vector Word16
s, Int -> Vector Word16 -> Vector Word16
forall a. Int -> Vector a -> Vector a
DV.take (Vector Word16 -> Int
forall a. Vector a -> Int
DV.length Vector Word16
s Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Vector Word16
s)
  {-# INLINE unsnoc   #-}

instance Unsnoc (DV.Vector Word32) where
  unsnoc :: Vector Word32 -> Maybe (Elem (Vector Word32), Vector Word32)
unsnoc Vector Word32
s = if Vector Word32 -> Int
forall a. Vector a -> Int
DV.length Vector Word32
s Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 then Maybe (Elem (Vector Word32), Vector Word32)
forall a. Maybe a
Nothing else (Word32, Vector Word32) -> Maybe (Word32, Vector Word32)
forall a. a -> Maybe a
Just (Vector Word32 -> Word32
forall a. Vector a -> a
DV.last Vector Word32
s, Int -> Vector Word32 -> Vector Word32
forall a. Int -> Vector a -> Vector a
DV.take (Vector Word32 -> Int
forall a. Vector a -> Int
DV.length Vector Word32
s Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Vector Word32
s)
  {-# INLINE unsnoc   #-}

instance Unsnoc (DV.Vector Word64) where
  unsnoc :: Vector Word64 -> Maybe (Elem (Vector Word64), Vector Word64)
unsnoc Vector Word64
s = if Vector Word64 -> Int
forall a. Vector a -> Int
DV.length Vector Word64
s Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 then Maybe (Elem (Vector Word64), Vector Word64)
forall a. Maybe a
Nothing else (Word64, Vector Word64) -> Maybe (Word64, Vector Word64)
forall a. a -> Maybe a
Just (Vector Word64 -> Word64
forall a. Vector a -> a
DV.last Vector Word64
s, Int -> Vector Word64 -> Vector Word64
forall a. Int -> Vector a -> Vector a
DV.take (Vector Word64 -> Int
forall a. Vector a -> Int
DV.length Vector Word64
s Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Vector Word64
s)
  {-# INLINE unsnoc   #-}

instance Unsnoc (DVS.Vector Word8) where
  unsnoc :: Vector Word8 -> Maybe (Elem (Vector Word8), Vector Word8)
unsnoc Vector Word8
s = if Vector Word8 -> Int
forall a. Storable a => Vector a -> Int
DVS.length Vector Word8
s Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 then Maybe (Elem (Vector Word8), Vector Word8)
forall a. Maybe a
Nothing else (Word8, Vector Word8) -> Maybe (Word8, Vector Word8)
forall a. a -> Maybe a
Just (Vector Word8 -> Word8
forall a. Storable a => Vector a -> a
DVS.last Vector Word8
s, Int -> Vector Word8 -> Vector Word8
forall a. Storable a => Int -> Vector a -> Vector a
DVS.take (Vector Word8 -> Int
forall a. Storable a => Vector a -> Int
DVS.length Vector Word8
s Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Vector Word8
s)
  {-# INLINE unsnoc   #-}

instance Unsnoc (DVS.Vector Word16) where
  unsnoc :: Vector Word16 -> Maybe (Elem (Vector Word16), Vector Word16)
unsnoc Vector Word16
s = if Vector Word16 -> Int
forall a. Storable a => Vector a -> Int
DVS.length Vector Word16
s Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 then Maybe (Elem (Vector Word16), Vector Word16)
forall a. Maybe a
Nothing else (Word16, Vector Word16) -> Maybe (Word16, Vector Word16)
forall a. a -> Maybe a
Just (Vector Word16 -> Word16
forall a. Storable a => Vector a -> a
DVS.last Vector Word16
s, Int -> Vector Word16 -> Vector Word16
forall a. Storable a => Int -> Vector a -> Vector a
DVS.take (Vector Word16 -> Int
forall a. Storable a => Vector a -> Int
DVS.length Vector Word16
s Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Vector Word16
s)
  {-# INLINE unsnoc   #-}

instance Unsnoc (DVS.Vector Word32) where
  unsnoc :: Vector Word32 -> Maybe (Elem (Vector Word32), Vector Word32)
unsnoc Vector Word32
s = if Vector Word32 -> Int
forall a. Storable a => Vector a -> Int
DVS.length Vector Word32
s Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 then Maybe (Elem (Vector Word32), Vector Word32)
forall a. Maybe a
Nothing else (Word32, Vector Word32) -> Maybe (Word32, Vector Word32)
forall a. a -> Maybe a
Just (Vector Word32 -> Word32
forall a. Storable a => Vector a -> a
DVS.last Vector Word32
s, Int -> Vector Word32 -> Vector Word32
forall a. Storable a => Int -> Vector a -> Vector a
DVS.take (Vector Word32 -> Int
forall a. Storable a => Vector a -> Int
DVS.length Vector Word32
s Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Vector Word32
s)
  {-# INLINE unsnoc   #-}

instance Unsnoc (DVS.Vector Word64) where
  unsnoc :: Vector Word64 -> Maybe (Elem (Vector Word64), Vector Word64)
unsnoc Vector Word64
s = if Vector Word64 -> Int
forall a. Storable a => Vector a -> Int
DVS.length Vector Word64
s Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 then Maybe (Elem (Vector Word64), Vector Word64)
forall a. Maybe a
Nothing else (Word64, Vector Word64) -> Maybe (Word64, Vector Word64)
forall a. a -> Maybe a
Just (Vector Word64 -> Word64
forall a. Storable a => Vector a -> a
DVS.last Vector Word64
s, Int -> Vector Word64 -> Vector Word64
forall a. Storable a => Int -> Vector a -> Vector a
DVS.take (Vector Word64 -> Int
forall a. Storable a => Vector a -> Int
DVS.length Vector Word64
s Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Vector Word64
s)
  {-# INLINE unsnoc   #-}

instance Unsnoc (DV.Vector Int8) where
  unsnoc :: Vector Int8 -> Maybe (Elem (Vector Int8), Vector Int8)
unsnoc Vector Int8
s = if Vector Int8 -> Int
forall a. Vector a -> Int
DV.length Vector Int8
s Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 then Maybe (Elem (Vector Int8), Vector Int8)
forall a. Maybe a
Nothing else (Int8, Vector Int8) -> Maybe (Int8, Vector Int8)
forall a. a -> Maybe a
Just (Vector Int8 -> Int8
forall a. Vector a -> a
DV.last Vector Int8
s, Int -> Vector Int8 -> Vector Int8
forall a. Int -> Vector a -> Vector a
DV.take (Vector Int8 -> Int
forall a. Vector a -> Int
DV.length Vector Int8
s Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Vector Int8
s)
  {-# INLINE unsnoc   #-}

instance Unsnoc (DV.Vector Int16) where
  unsnoc :: Vector Int16 -> Maybe (Elem (Vector Int16), Vector Int16)
unsnoc Vector Int16
s = if Vector Int16 -> Int
forall a. Vector a -> Int
DV.length Vector Int16
s Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 then Maybe (Elem (Vector Int16), Vector Int16)
forall a. Maybe a
Nothing else (Int16, Vector Int16) -> Maybe (Int16, Vector Int16)
forall a. a -> Maybe a
Just (Vector Int16 -> Int16
forall a. Vector a -> a
DV.last Vector Int16
s, Int -> Vector Int16 -> Vector Int16
forall a. Int -> Vector a -> Vector a
DV.take (Vector Int16 -> Int
forall a. Vector a -> Int
DV.length Vector Int16
s Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Vector Int16
s)
  {-# INLINE unsnoc   #-}

instance Unsnoc (DV.Vector Int32) where
  unsnoc :: Vector Int32 -> Maybe (Elem (Vector Int32), Vector Int32)
unsnoc Vector Int32
s = if Vector Int32 -> Int
forall a. Vector a -> Int
DV.length Vector Int32
s Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 then Maybe (Elem (Vector Int32), Vector Int32)
forall a. Maybe a
Nothing else (Int32, Vector Int32) -> Maybe (Int32, Vector Int32)
forall a. a -> Maybe a
Just (Vector Int32 -> Int32
forall a. Vector a -> a
DV.last Vector Int32
s, Int -> Vector Int32 -> Vector Int32
forall a. Int -> Vector a -> Vector a
DV.take (Vector Int32 -> Int
forall a. Vector a -> Int
DV.length Vector Int32
s Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Vector Int32
s)
  {-# INLINE unsnoc   #-}

instance Unsnoc (DV.Vector Int64) where
  unsnoc :: Vector Int64 -> Maybe (Elem (Vector Int64), Vector Int64)
unsnoc Vector Int64
s = if Vector Int64 -> Int
forall a. Vector a -> Int
DV.length Vector Int64
s Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 then Maybe (Elem (Vector Int64), Vector Int64)
forall a. Maybe a
Nothing else (Int64, Vector Int64) -> Maybe (Int64, Vector Int64)
forall a. a -> Maybe a
Just (Vector Int64 -> Int64
forall a. Vector a -> a
DV.last Vector Int64
s, Int -> Vector Int64 -> Vector Int64
forall a. Int -> Vector a -> Vector a
DV.take (Vector Int64 -> Int
forall a. Vector a -> Int
DV.length Vector Int64
s Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Vector Int64
s)
  {-# INLINE unsnoc   #-}

instance Unsnoc (DVS.Vector Int8) where
  unsnoc :: Vector Int8 -> Maybe (Elem (Vector Int8), Vector Int8)
unsnoc Vector Int8
s = if Vector Int8 -> Int
forall a. Storable a => Vector a -> Int
DVS.length Vector Int8
s Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 then Maybe (Elem (Vector Int8), Vector Int8)
forall a. Maybe a
Nothing else (Int8, Vector Int8) -> Maybe (Int8, Vector Int8)
forall a. a -> Maybe a
Just (Vector Int8 -> Int8
forall a. Storable a => Vector a -> a
DVS.last Vector Int8
s, Int -> Vector Int8 -> Vector Int8
forall a. Storable a => Int -> Vector a -> Vector a
DVS.take (Vector Int8 -> Int
forall a. Storable a => Vector a -> Int
DVS.length Vector Int8
s Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Vector Int8
s)
  {-# INLINE unsnoc   #-}

instance Unsnoc (DVS.Vector Int16) where
  unsnoc :: Vector Int16 -> Maybe (Elem (Vector Int16), Vector Int16)
unsnoc Vector Int16
s = if Vector Int16 -> Int
forall a. Storable a => Vector a -> Int
DVS.length Vector Int16
s Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 then Maybe (Elem (Vector Int16), Vector Int16)
forall a. Maybe a
Nothing else (Int16, Vector Int16) -> Maybe (Int16, Vector Int16)
forall a. a -> Maybe a
Just (Vector Int16 -> Int16
forall a. Storable a => Vector a -> a
DVS.last Vector Int16
s, Int -> Vector Int16 -> Vector Int16
forall a. Storable a => Int -> Vector a -> Vector a
DVS.take (Vector Int16 -> Int
forall a. Storable a => Vector a -> Int
DVS.length Vector Int16
s Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Vector Int16
s)
  {-# INLINE unsnoc   #-}

instance Unsnoc (DVS.Vector Int32) where
  unsnoc :: Vector Int32 -> Maybe (Elem (Vector Int32), Vector Int32)
unsnoc Vector Int32
s = if Vector Int32 -> Int
forall a. Storable a => Vector a -> Int
DVS.length Vector Int32
s Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 then Maybe (Elem (Vector Int32), Vector Int32)
forall a. Maybe a
Nothing else (Int32, Vector Int32) -> Maybe (Int32, Vector Int32)
forall a. a -> Maybe a
Just (Vector Int32 -> Int32
forall a. Storable a => Vector a -> a
DVS.last Vector Int32
s, Int -> Vector Int32 -> Vector Int32
forall a. Storable a => Int -> Vector a -> Vector a
DVS.take (Vector Int32 -> Int
forall a. Storable a => Vector a -> Int
DVS.length Vector Int32
s Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Vector Int32
s)
  {-# INLINE unsnoc   #-}

instance Unsnoc (DVS.Vector Int64) where
  unsnoc :: Vector Int64 -> Maybe (Elem (Vector Int64), Vector Int64)
unsnoc Vector Int64
s = if Vector Int64 -> Int
forall a. Storable a => Vector a -> Int
DVS.length Vector Int64
s Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 then Maybe (Elem (Vector Int64), Vector Int64)
forall a. Maybe a
Nothing else (Int64, Vector Int64) -> Maybe (Int64, Vector Int64)
forall a. a -> Maybe a
Just (Vector Int64 -> Int64
forall a. Storable a => Vector a -> a
DVS.last Vector Int64
s, Int -> Vector Int64 -> Vector Int64
forall a. Storable a => Int -> Vector a -> Vector a
DVS.take (Vector Int64 -> Int
forall a. Storable a => Vector a -> Int
DVS.length Vector Int64
s Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Vector Int64
s)
  {-# INLINE unsnoc   #-}

instance Unsnoc (DVS.Vector Int) where
  unsnoc :: Vector Int -> Maybe (Elem (Vector Int), Vector Int)
unsnoc Vector Int
s = if Vector Int -> Int
forall a. Storable a => Vector a -> Int
DVS.length Vector Int
s Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 then Maybe (Elem (Vector Int), Vector Int)
forall a. Maybe a
Nothing else (Int, Vector Int) -> Maybe (Int, Vector Int)
forall a. a -> Maybe a
Just (Vector Int -> Int
forall a. Storable a => Vector a -> a
DVS.last Vector Int
s, Int -> Vector Int -> Vector Int
forall a. Storable a => Int -> Vector a -> Vector a
DVS.take (Vector Int -> Int
forall a. Storable a => Vector a -> Int
DVS.length Vector Int
s Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Vector Int
s)
  {-# INLINE unsnoc   #-}