    {-# LANGUAGE FlexibleContexts #-}
    {-# LANGUAGE ConstraintKinds  #-}
    {-# LANGUAGE TupleSections    #-}
    {- |
    Provides functions that raise errors in corner cases instead of returning \"best effort\"
    results, then provides wrappers like the "Safe" module. For example:

    * @'takeExact' 3 [1,2]@ raises an error, in contrast to 'take' which would return
      just two elements.

    * @'takeExact' (-1) [1,2]@ raises an error, in contrast to 'take' which would return
      no elements.

    * @'zip' [1,2] [1]@ raises an error, in contrast to 'zip' which would only pair up the
      first element.

    Note that the @May@ variants of these functions are /strict/ in at least the bit of the prefix
    of the list required to spot errors. The standard and @Note@ versions are lazy, but throw
    errors later in the process - they do not check upfront.
    -}
    module Safe.Exact(
        -- * New functions
        takeExact, dropExact, splitAtExact,
        zipExact, zipWithExact,
        zip3Exact, zipWith3Exact,
        -- * Safe wrappers
        takeExactMay, takeExactNote, takeExactDef,
        dropExactMay, dropExactNote, dropExactDef,
        splitAtExactMay, splitAtExactNote, splitAtExactDef,
        zipExactMay, zipExactNote, zipExactDef,
        zipWithExactMay, zipWithExactNote, zipWithExactDef,
        zip3ExactMay, zip3ExactNote, zip3ExactDef,
        zipWith3ExactMay, zipWith3ExactNote, zipWith3ExactDef,
        ) where

    import Control.Arrow
    import Data.Maybe
    import Safe.Util
    import Safe.Partial

    ---------------------------------------------------------------------
    -- HELPERS

    addNote :: Partial => String -> String -> String -> a
    addNote :: String -> String -> String -> a
    addNote note :: String
    note fun :: String
    fun msg :: String
    msg = String -> a
    forall a. HasCallStack => String -> a
    error (String -> a) -> String -> a
    forall a b. (a -> b) -> a -> b
    $
        "Safe.Exact." String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    fun String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ ", " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    msg String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ (if String -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null String
    note then "" else ", " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    note)

    ---------------------------------------------------------------------
    -- IMPLEMENTATIONS

    {-# INLINE splitAtExact_ #-}
    splitAtExact_ :: Partial => (String -> r) -> ([a] -> r) -> (a -> r -> r) -> Int -> [a] -> r
    splitAtExact_ :: (String -> r) -> ([a] -> r) -> (a -> r -> r) -> Int -> [a] -> r
    splitAtExact_ err :: String -> r
    err nil :: [a] -> r
    nil cons :: a -> r -> r
    cons o :: Int
    o xs :: [a]
    xs
        | Int
    o Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < 0 = String -> r
    err (String -> r) -> String -> r
    forall a b. (a -> b) -> a -> b
    $ "index must not be negative, index=" String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ Int -> String
    forall a. Show a => a -> String
    show Int
    o
        | Bool
    otherwise = Int -> [a] -> r
    f Int
    o [a]
    xs
        where
            f :: Int -> [a] -> r
    f 0 xs :: [a]
    xs = [a] -> r
    nil [a]
    xs
            f i :: Int
    i (x :: a
    x:xs :: [a]
    xs) = a
    x a -> r -> r
    `cons` Int -> [a] -> r
    f (Int
    iInt -> Int -> Int
    forall a. Num a => a -> a -> a
    -1) [a]
    xs
            f i :: Int
    i [] = String -> r
    err (String -> r) -> String -> r
    forall a b. (a -> b) -> a -> b
    $ "index too large, index=" String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ Int -> String
    forall a. Show a => a -> String
    show Int
    o String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ ", length=" String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ Int -> String
    forall a. Show a => a -> String
    show (Int
    oInt -> Int -> Int
    forall a. Num a => a -> a -> a
    -Int
    i)

    {-# INLINE zipWithExact_ #-}
    zipWithExact_ :: Partial => (String -> r) -> r -> (a -> b -> r -> r) -> [a] -> [b] -> r
    zipWithExact_ :: (String -> r) -> r -> (a -> b -> r -> r) -> [a] -> [b] -> r
    zipWithExact_ err :: String -> r
    err nil :: r
    nil cons :: a -> b -> r -> r
    cons = [a] -> [b] -> r
    f
        where
            f :: [a] -> [b] -> r
    f (x :: a
    x:xs :: [a]
    xs) (y :: b
    y:ys :: [b]
    ys) = a -> b -> r -> r
    cons a
    x b
    y (r -> r) -> r -> r
    forall a b. (a -> b) -> a -> b
    $ [a] -> [b] -> r
    f [a]
    xs [b]
    ys
            f [] [] = r
    nil
            f [] _ = String -> r
    err "second list is longer than the first"
            f _ [] = String -> r
    err "first list is longer than the second"

    {-# INLINE zipWith3Exact_ #-}
    zipWith3Exact_ :: Partial => (String -> r) -> r -> (a -> b -> c -> r -> r) -> [a] -> [b] -> [c] -> r
    zipWith3Exact_ :: (String -> r)
    -> r -> (a -> b -> c -> r -> r) -> [a] -> [b] -> [c] -> r
    zipWith3Exact_ err :: String -> r
    err nil :: r
    nil cons :: a -> b -> c -> r -> r
    cons = [a] -> [b] -> [c] -> r
    f
        where
            f :: [a] -> [b] -> [c] -> r
    f (x :: a
    x:xs :: [a]
    xs) (y :: b
    y:ys :: [b]
    ys) (z :: c
    z:zs :: [c]
    zs) = a -> b -> c -> r -> r
    cons a
    x b
    y c
    z (r -> r) -> r -> r
    forall a b. (a -> b) -> a -> b
    $ [a] -> [b] -> [c] -> r
    f [a]
    xs [b]
    ys [c]
    zs
            f [] [] [] = r
    nil
            f [] _ _ = String -> r
    err "first list is shorter than the others"
            f _ [] _ = String -> r
    err "second list is shorter than the others"
            f _ _ [] = String -> r
    err "third list is shorter than the others"

    ---------------------------------------------------------------------
    -- TAKE/DROP/SPLIT

    -- |
    -- > takeExact n xs =
    -- >   | n >= 0 && n <= length xs = take n xs
    -- >   | otherwise                = error "some message"
    takeExact :: Partial => Int -> [a] -> [a]
    takeExact :: Int -> [a] -> [a]
    takeExact i :: Int
    i xs :: [a]
    xs = (HasCallStack => [a]) -> [a]
    forall a. HasCallStack => (HasCallStack => a) -> a
    withFrozenCallStack ((HasCallStack => [a]) -> [a]) -> (HasCallStack => [a]) -> [a]
    forall a b. (a -> b) -> a -> b
    $ (String -> [a])
    -> ([a] -> [a]) -> (a -> [a] -> [a]) -> Int -> [a] -> [a]
    forall r a.
    HasCallStack =>
    (String -> r) -> ([a] -> r) -> (a -> r -> r) -> Int -> [a] -> r
    splitAtExact_ (String -> String -> String -> [a]
    forall a. HasCallStack => String -> String -> String -> a
    addNote "" "takeExact") ([a] -> [a] -> [a]
    forall a b. a -> b -> a
    const []) (:) Int
    i [a]
    xs

    -- |
    -- > dropExact n xs =
    -- >   | n >= 0 && n <= length xs = drop n xs
    -- >   | otherwise                = error "some message"
    dropExact :: Partial => Int -> [a] -> [a]
    dropExact :: Int -> [a] -> [a]
    dropExact i :: Int
    i xs :: [a]
    xs = (HasCallStack => [a]) -> [a]
    forall a. HasCallStack => (HasCallStack => a) -> a
    withFrozenCallStack ((HasCallStack => [a]) -> [a]) -> (HasCallStack => [a]) -> [a]
    forall a b. (a -> b) -> a -> b
    $ (String -> [a])
    -> ([a] -> [a]) -> (a -> [a] -> [a]) -> Int -> [a] -> [a]
    forall r a.
    HasCallStack =>
    (String -> r) -> ([a] -> r) -> (a -> r -> r) -> Int -> [a] -> r
    splitAtExact_ (String -> String -> String -> [a]
    forall a. HasCallStack => String -> String -> String -> a
    addNote "" "dropExact") [a] -> [a]
    forall a. a -> a
    id (([a] -> a -> [a]) -> a -> [a] -> [a]
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip [a] -> a -> [a]
    forall a b. a -> b -> a
    const) Int
    i [a]
    xs

    -- |
    -- > splitAtExact n xs =
    -- >   | n >= 0 && n <= length xs = splitAt n xs
    -- >   | otherwise                = error "some message"
    splitAtExact :: Partial => Int -> [a] -> ([a], [a])
    splitAtExact :: Int -> [a] -> ([a], [a])
    splitAtExact i :: Int
    i xs :: [a]
    xs = (HasCallStack => ([a], [a])) -> ([a], [a])
    forall a. HasCallStack => (HasCallStack => a) -> a
    withFrozenCallStack ((HasCallStack => ([a], [a])) -> ([a], [a]))
    -> (HasCallStack => ([a], [a])) -> ([a], [a])
    forall a b. (a -> b) -> a -> b
    $ (String -> ([a], [a]))
    -> ([a] -> ([a], [a]))
    -> (a -> ([a], [a]) -> ([a], [a]))
    -> Int
    -> [a]
    -> ([a], [a])
    forall r a.
    HasCallStack =>
    (String -> r) -> ([a] -> r) -> (a -> r -> r) -> Int -> [a] -> r
    splitAtExact_ (String -> String -> String -> ([a], [a])
    forall a. HasCallStack => String -> String -> String -> a
    addNote "" "splitAtExact")
        ([],) (\a :: a
    a b :: ([a], [a])
    b -> ([a] -> [a]) -> ([a], [a]) -> ([a], [a])
    forall (a :: * -> * -> *) b c d.
    Arrow a =>
    a b c -> a (b, d) (c, d)
    first (a
    aa -> [a] -> [a]
    forall a. a -> [a] -> [a]
    :) ([a], [a])
    b) Int
    i [a]
    xs

    takeExactNote :: Partial => String -> Int -> [a] -> [a]
    takeExactNote :: String -> Int -> [a] -> [a]
    takeExactNote note :: String
    note i :: Int
    i xs :: [a]
    xs = (HasCallStack => [a]) -> [a]
    forall a. HasCallStack => (HasCallStack => a) -> a
    withFrozenCallStack ((HasCallStack => [a]) -> [a]) -> (HasCallStack => [a]) -> [a]
    forall a b. (a -> b) -> a -> b
    $ (String -> [a])
    -> ([a] -> [a]) -> (a -> [a] -> [a]) -> Int -> [a] -> [a]
    forall r a.
    HasCallStack =>
    (String -> r) -> ([a] -> r) -> (a -> r -> r) -> Int -> [a] -> r
    splitAtExact_ (String -> String -> String -> [a]
    forall a. HasCallStack => String -> String -> String -> a
    addNote String
    note "takeExactNote") ([a] -> [a] -> [a]
    forall a b. a -> b -> a
    const []) (:) Int
    i [a]
    xs

    takeExactMay :: Int -> [a] -> Maybe [a]
    takeExactMay :: Int -> [a] -> Maybe [a]
    takeExactMay = (String -> Maybe [a])
    -> ([a] -> Maybe [a])
    -> (a -> Maybe [a] -> Maybe [a])
    -> Int
    -> [a]
    -> Maybe [a]
    forall r a.
    HasCallStack =>
    (String -> r) -> ([a] -> r) -> (a -> r -> r) -> Int -> [a] -> r
    splitAtExact_ (Maybe [a] -> String -> Maybe [a]
    forall a b. a -> b -> a
    const Maybe [a]
    forall a. Maybe a
    Nothing) (Maybe [a] -> [a] -> Maybe [a]
    forall a b. a -> b -> a
    const (Maybe [a] -> [a] -> Maybe [a]) -> Maybe [a] -> [a] -> Maybe [a]
    forall a b. (a -> b) -> a -> b
    $ [a] -> Maybe [a]
    forall a. a -> Maybe a
    Just []) (\a :: a
    a -> ([a] -> [a]) -> Maybe [a] -> Maybe [a]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (a
    aa -> [a] -> [a]
    forall a. a -> [a] -> [a]
    :))

    takeExactDef :: [a] -> Int -> [a] -> [a]
    takeExactDef :: [a] -> Int -> [a] -> [a]
    takeExactDef def :: [a]
    def = [a] -> Maybe [a] -> [a]
    forall a. a -> Maybe a -> a
    fromMaybe [a]
    def (Maybe [a] -> [a])
    -> (Int -> [a] -> Maybe [a]) -> Int -> [a] -> [a]
    forall b c a1 a2.
    HasCallStack =>
    (b -> c) -> (a1 -> a2 -> b) -> a1 -> a2 -> c
    .^ Int -> [a] -> Maybe [a]
    forall a. Int -> [a] -> Maybe [a]
    takeExactMay

    dropExactNote :: Partial => String -> Int -> [a] -> [a]
    dropExactNote :: String -> Int -> [a] -> [a]
    dropExactNote note :: String
    note i :: Int
    i xs :: [a]
    xs = (HasCallStack => [a]) -> [a]
    forall a. HasCallStack => (HasCallStack => a) -> a
    withFrozenCallStack ((HasCallStack => [a]) -> [a]) -> (HasCallStack => [a]) -> [a]
    forall a b. (a -> b) -> a -> b
    $ (String -> [a])
    -> ([a] -> [a]) -> (a -> [a] -> [a]) -> Int -> [a] -> [a]
    forall r a.
    HasCallStack =>
    (String -> r) -> ([a] -> r) -> (a -> r -> r) -> Int -> [a] -> r
    splitAtExact_ (String -> String -> String -> [a]
    forall a. HasCallStack => String -> String -> String -> a
    addNote String
    note "dropExactNote") [a] -> [a]
    forall a. a -> a
    id (([a] -> a -> [a]) -> a -> [a] -> [a]
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip [a] -> a -> [a]
    forall a b. a -> b -> a
    const) Int
    i [a]
    xs

    dropExactMay :: Int -> [a] -> Maybe [a]
    dropExactMay :: Int -> [a] -> Maybe [a]
    dropExactMay = (String -> Maybe [a])
    -> ([a] -> Maybe [a])
    -> (a -> Maybe [a] -> Maybe [a])
    -> Int
    -> [a]
    -> Maybe [a]
    forall r a.
    HasCallStack =>
    (String -> r) -> ([a] -> r) -> (a -> r -> r) -> Int -> [a] -> r
    splitAtExact_ (Maybe [a] -> String -> Maybe [a]
    forall a b. a -> b -> a
    const Maybe [a]
    forall a. Maybe a
    Nothing) [a] -> Maybe [a]
    forall a. a -> Maybe a
    Just ((Maybe [a] -> a -> Maybe [a]) -> a -> Maybe [a] -> Maybe [a]
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip Maybe [a] -> a -> Maybe [a]
    forall a b. a -> b -> a
    const)

    dropExactDef :: [a] -> Int -> [a] -> [a]
    dropExactDef :: [a] -> Int -> [a] -> [a]
    dropExactDef def :: [a]
    def = [a] -> Maybe [a] -> [a]
    forall a. a -> Maybe a -> a
    fromMaybe [a]
    def (Maybe [a] -> [a])
    -> (Int -> [a] -> Maybe [a]) -> Int -> [a] -> [a]
    forall b c a1 a2.
    HasCallStack =>
    (b -> c) -> (a1 -> a2 -> b) -> a1 -> a2 -> c
    .^ Int -> [a] -> Maybe [a]
    forall a. Int -> [a] -> Maybe [a]
    dropExactMay

    splitAtExactNote :: Partial => String -> Int -> [a] -> ([a], [a])
    splitAtExactNote :: String -> Int -> [a] -> ([a], [a])
    splitAtExactNote note :: String
    note i :: Int
    i xs :: [a]
    xs = (HasCallStack => ([a], [a])) -> ([a], [a])
    forall a. HasCallStack => (HasCallStack => a) -> a
    withFrozenCallStack ((HasCallStack => ([a], [a])) -> ([a], [a]))
    -> (HasCallStack => ([a], [a])) -> ([a], [a])
    forall a b. (a -> b) -> a -> b
    $ (String -> ([a], [a]))
    -> ([a] -> ([a], [a]))
    -> (a -> ([a], [a]) -> ([a], [a]))
    -> Int
    -> [a]
    -> ([a], [a])
    forall r a.
    HasCallStack =>
    (String -> r) -> ([a] -> r) -> (a -> r -> r) -> Int -> [a] -> r
    splitAtExact_ (String -> String -> String -> ([a], [a])
    forall a. HasCallStack => String -> String -> String -> a
    addNote String
    note "splitAtExactNote")
        ([],) (\a :: a
    a b :: ([a], [a])
    b -> ([a] -> [a]) -> ([a], [a]) -> ([a], [a])
    forall (a :: * -> * -> *) b c d.
    Arrow a =>
    a b c -> a (b, d) (c, d)
    first (a
    aa -> [a] -> [a]
    forall a. a -> [a] -> [a]
    :) ([a], [a])
    b) Int
    i [a]
    xs

    splitAtExactMay :: Int -> [a] -> Maybe ([a], [a])
    splitAtExactMay :: Int -> [a] -> Maybe ([a], [a])
    splitAtExactMay = (String -> Maybe ([a], [a]))
    -> ([a] -> Maybe ([a], [a]))
    -> (a -> Maybe ([a], [a]) -> Maybe ([a], [a]))
    -> Int
    -> [a]
    -> Maybe ([a], [a])
    forall r a.
    HasCallStack =>
    (String -> r) -> ([a] -> r) -> (a -> r -> r) -> Int -> [a] -> r
    splitAtExact_ (Maybe ([a], [a]) -> String -> Maybe ([a], [a])
    forall a b. a -> b -> a
    const Maybe ([a], [a])
    forall a. Maybe a
    Nothing)
        (\x :: [a]
    x -> ([a], [a]) -> Maybe ([a], [a])
    forall a. a -> Maybe a
    Just ([], [a]
    x)) (\a :: a
    a b :: Maybe ([a], [a])
    b -> (([a], [a]) -> ([a], [a])) -> Maybe ([a], [a]) -> Maybe ([a], [a])
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (([a] -> [a]) -> ([a], [a]) -> ([a], [a])
    forall (a :: * -> * -> *) b c d.
    Arrow a =>
    a b c -> a (b, d) (c, d)
    first (a
    aa -> [a] -> [a]
    forall a. a -> [a] -> [a]
    :)) Maybe ([a], [a])
    b)

    splitAtExactDef :: ([a], [a]) -> Int -> [a] -> ([a], [a])
    splitAtExactDef :: ([a], [a]) -> Int -> [a] -> ([a], [a])
    splitAtExactDef def :: ([a], [a])
    def = ([a], [a]) -> Maybe ([a], [a]) -> ([a], [a])
    forall a. a -> Maybe a -> a
    fromMaybe ([a], [a])
    def (Maybe ([a], [a]) -> ([a], [a]))
    -> (Int -> [a] -> Maybe ([a], [a])) -> Int -> [a] -> ([a], [a])
    forall b c a1 a2.
    HasCallStack =>
    (b -> c) -> (a1 -> a2 -> b) -> a1 -> a2 -> c
    .^ Int -> [a] -> Maybe ([a], [a])
    forall a. Int -> [a] -> Maybe ([a], [a])
    splitAtExactMay

    ---------------------------------------------------------------------
    -- ZIP

    -- |
    -- > zipExact xs ys =
    -- >   | length xs == length ys = zip xs ys
    -- >   | otherwise              = error "some message"
    zipExact :: Partial => [a] -> [b] -> [(a,b)]
    zipExact :: [a] -> [b] -> [(a, b)]
    zipExact xs :: [a]
    xs ys :: [b]
    ys = (HasCallStack => [(a, b)]) -> [(a, b)]
    forall a. HasCallStack => (HasCallStack => a) -> a
    withFrozenCallStack ((HasCallStack => [(a, b)]) -> [(a, b)])
    -> (HasCallStack => [(a, b)]) -> [(a, b)]
    forall a b. (a -> b) -> a -> b
    $ (String -> [(a, b)])
    -> [(a, b)]
    -> (a -> b -> [(a, b)] -> [(a, b)])
    -> [a]
    -> [b]
    -> [(a, b)]
    forall r a b.
    HasCallStack =>
    (String -> r) -> r -> (a -> b -> r -> r) -> [a] -> [b] -> r
    zipWithExact_ (String -> String -> String -> [(a, b)]
    forall a. HasCallStack => String -> String -> String -> a
    addNote "" "zipExact") []  (\a :: a
    a b :: b
    b xs :: [(a, b)]
    xs -> (a
    a,b
    b) (a, b) -> [(a, b)] -> [(a, b)]
    forall a. a -> [a] -> [a]
    : [(a, b)]
    xs) [a]
    xs [b]
    ys

    -- |
    -- > zipWithExact f xs ys =
    -- >   | length xs == length ys = zipWith f xs ys
    -- >   | otherwise              = error "some message"
    zipWithExact :: Partial => (a -> b -> c) -> [a] -> [b] -> [c]
    zipWithExact :: (a -> b -> c) -> [a] -> [b] -> [c]
    zipWithExact f :: a -> b -> c
    f xs :: [a]
    xs ys :: [b]
    ys = (HasCallStack => [c]) -> [c]
    forall a. HasCallStack => (HasCallStack => a) -> a
    withFrozenCallStack ((HasCallStack => [c]) -> [c]) -> (HasCallStack => [c]) -> [c]
    forall a b. (a -> b) -> a -> b
    $ (String -> [c])
    -> [c] -> (a -> b -> [c] -> [c]) -> [a] -> [b] -> [c]
    forall r a b.
    HasCallStack =>
    (String -> r) -> r -> (a -> b -> r -> r) -> [a] -> [b] -> r
    zipWithExact_ (String -> String -> String -> [c]
    forall a. HasCallStack => String -> String -> String -> a
    addNote "" "zipWithExact") [] (\a :: a
    a b :: b
    b xs :: [c]
    xs -> a -> b -> c
    f a
    a b
    b c -> [c] -> [c]
    forall a. a -> [a] -> [a]
    : [c]
    xs) [a]
    xs [b]
    ys

    zipExactNote :: Partial => String -> [a] -> [b] -> [(a,b)]
    zipExactNote :: String -> [a] -> [b] -> [(a, b)]
    zipExactNote note :: String
    note xs :: [a]
    xs ys :: [b]
    ys = (HasCallStack => [(a, b)]) -> [(a, b)]
    forall a. HasCallStack => (HasCallStack => a) -> a
    withFrozenCallStack ((HasCallStack => [(a, b)]) -> [(a, b)])
    -> (HasCallStack => [(a, b)]) -> [(a, b)]
    forall a b. (a -> b) -> a -> b
    $ (String -> [(a, b)])
    -> [(a, b)]
    -> (a -> b -> [(a, b)] -> [(a, b)])
    -> [a]
    -> [b]
    -> [(a, b)]
    forall r a b.
    HasCallStack =>
    (String -> r) -> r -> (a -> b -> r -> r) -> [a] -> [b] -> r
    zipWithExact_ (String -> String -> String -> [(a, b)]
    forall a. HasCallStack => String -> String -> String -> a
    addNote String
    note "zipExactNote") []  (\a :: a
    a b :: b
    b xs :: [(a, b)]
    xs -> (a
    a,b
    b) (a, b) -> [(a, b)] -> [(a, b)]
    forall a. a -> [a] -> [a]
    : [(a, b)]
    xs) [a]
    xs [b]
    ys

    zipExactMay :: [a] -> [b] -> Maybe [(a,b)]
    zipExactMay :: [a] -> [b] -> Maybe [(a, b)]
    zipExactMay = (String -> Maybe [(a, b)])
    -> Maybe [(a, b)]
    -> (a -> b -> Maybe [(a, b)] -> Maybe [(a, b)])
    -> [a]
    -> [b]
    -> Maybe [(a, b)]
    forall r a b.
    HasCallStack =>
    (String -> r) -> r -> (a -> b -> r -> r) -> [a] -> [b] -> r
    zipWithExact_ (Maybe [(a, b)] -> String -> Maybe [(a, b)]
    forall a b. a -> b -> a
    const Maybe [(a, b)]
    forall a. Maybe a
    Nothing) ([(a, b)] -> Maybe [(a, b)]
    forall a. a -> Maybe a
    Just [])  (\a :: a
    a b :: b
    b xs :: Maybe [(a, b)]
    xs -> ([(a, b)] -> [(a, b)]) -> Maybe [(a, b)] -> Maybe [(a, b)]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ((a
    a,b
    b) (a, b) -> [(a, b)] -> [(a, b)]
    forall a. a -> [a] -> [a]
    :) Maybe [(a, b)]
    xs)

    zipExactDef :: [(a,b)] -> [a] -> [b] -> [(a,b)]
    zipExactDef :: [(a, b)] -> [a] -> [b] -> [(a, b)]
    zipExactDef def :: [(a, b)]
    def = [(a, b)] -> Maybe [(a, b)] -> [(a, b)]
    forall a. a -> Maybe a -> a
    fromMaybe [(a, b)]
    def (Maybe [(a, b)] -> [(a, b)])
    -> ([a] -> [b] -> Maybe [(a, b)]) -> [a] -> [b] -> [(a, b)]
    forall b c a1 a2.
    HasCallStack =>
    (b -> c) -> (a1 -> a2 -> b) -> a1 -> a2 -> c
    .^ [a] -> [b] -> Maybe [(a, b)]
    forall a b. [a] -> [b] -> Maybe [(a, b)]
    zipExactMay

    zipWithExactNote :: Partial => String -> (a -> b -> c) -> [a] -> [b] -> [c]
    zipWithExactNote :: String -> (a -> b -> c) -> [a] -> [b] -> [c]
    zipWithExactNote note :: String
    note f :: a -> b -> c
    f xs :: [a]
    xs ys :: [b]
    ys = (HasCallStack => [c]) -> [c]
    forall a. HasCallStack => (HasCallStack => a) -> a
    withFrozenCallStack ((HasCallStack => [c]) -> [c]) -> (HasCallStack => [c]) -> [c]
    forall a b. (a -> b) -> a -> b
    $ (String -> [c])
    -> [c] -> (a -> b -> [c] -> [c]) -> [a] -> [b] -> [c]
    forall r a b.
    HasCallStack =>
    (String -> r) -> r -> (a -> b -> r -> r) -> [a] -> [b] -> r
    zipWithExact_ (String -> String -> String -> [c]
    forall a. HasCallStack => String -> String -> String -> a
    addNote String
    note "zipWithExactNote") []  (\a :: a
    a b :: b
    b xs :: [c]
    xs -> a -> b -> c
    f a
    a b
    b c -> [c] -> [c]
    forall a. a -> [a] -> [a]
    : [c]
    xs) [a]
    xs [b]
    ys

    zipWithExactMay :: (a -> b -> c) -> [a] -> [b] -> Maybe [c]
    zipWithExactMay :: (a -> b -> c) -> [a] -> [b] -> Maybe [c]
    zipWithExactMay f :: a -> b -> c
    f = (String -> Maybe [c])
    -> Maybe [c]
    -> (a -> b -> Maybe [c] -> Maybe [c])
    -> [a]
    -> [b]
    -> Maybe [c]
    forall r a b.
    HasCallStack =>
    (String -> r) -> r -> (a -> b -> r -> r) -> [a] -> [b] -> r
    zipWithExact_ (Maybe [c] -> String -> Maybe [c]
    forall a b. a -> b -> a
    const Maybe [c]
    forall a. Maybe a
    Nothing) ([c] -> Maybe [c]
    forall a. a -> Maybe a
    Just [])  (\a :: a
    a b :: b
    b xs :: Maybe [c]
    xs -> ([c] -> [c]) -> Maybe [c] -> Maybe [c]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (a -> b -> c
    f a
    a b
    b c -> [c] -> [c]
    forall a. a -> [a] -> [a]
    :) Maybe [c]
    xs)

    zipWithExactDef :: [c] -> (a -> b -> c) -> [a] -> [b] -> [c]
    zipWithExactDef :: [c] -> (a -> b -> c) -> [a] -> [b] -> [c]
    zipWithExactDef def :: [c]
    def = [c] -> Maybe [c] -> [c]
    forall a. a -> Maybe a -> a
    fromMaybe [c]
    def (Maybe [c] -> [c])
    -> ((a -> b -> c) -> [a] -> [b] -> Maybe [c])
    -> (a -> b -> c)
    -> [a]
    -> [b]
    -> [c]
    forall b c a1 a2 a3.
    HasCallStack =>
    (b -> c) -> (a1 -> a2 -> a3 -> b) -> a1 -> a2 -> a3 -> c
    .^^ (a -> b -> c) -> [a] -> [b] -> Maybe [c]
    forall a b c. (a -> b -> c) -> [a] -> [b] -> Maybe [c]
    zipWithExactMay

    -- |
    -- > zip3Exact xs ys zs =
    -- >   | length xs == length ys && length xs == length zs = zip3 xs ys zs
    -- >   | otherwise                                        = error "some message"
    zip3Exact :: Partial => [a] -> [b] -> [c] -> [(a,b,c)]
    zip3Exact :: [a] -> [b] -> [c] -> [(a, b, c)]
    zip3Exact xs :: [a]
    xs ys :: [b]
    ys zs :: [c]
    zs = (HasCallStack => [(a, b, c)]) -> [(a, b, c)]
    forall a. HasCallStack => (HasCallStack => a) -> a
    withFrozenCallStack ((HasCallStack => [(a, b, c)]) -> [(a, b, c)])
    -> (HasCallStack => [(a, b, c)]) -> [(a, b, c)]
    forall a b. (a -> b) -> a -> b
    $ (String -> [(a, b, c)])
    -> [(a, b, c)]
    -> (a -> b -> c -> [(a, b, c)] -> [(a, b, c)])
    -> [a]
    -> [b]
    -> [c]
    -> [(a, b, c)]
    forall r a b c.
    HasCallStack =>
    (String -> r)
    -> r -> (a -> b -> c -> r -> r) -> [a] -> [b] -> [c] -> r
    zipWith3Exact_ (String -> String -> String -> [(a, b, c)]
    forall a. HasCallStack => String -> String -> String -> a
    addNote "" "zip3Exact") [] (\a :: a
    a b :: b
    b c :: c
    c xs :: [(a, b, c)]
    xs -> (a
    a, b
    b, c
    c) (a, b, c) -> [(a, b, c)] -> [(a, b, c)]
    forall a. a -> [a] -> [a]
    : [(a, b, c)]
    xs) [a]
    xs [b]
    ys [c]
    zs

    -- |
    -- > zipWith3Exact f xs ys zs =
    -- >   | length xs == length ys && length xs == length zs = zipWith3 f xs ys zs
    -- >   | otherwise                                        = error "some message"
    zipWith3Exact :: Partial => (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]
    zipWith3Exact :: (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]
    zipWith3Exact f :: a -> b -> c -> d
    f xs :: [a]
    xs ys :: [b]
    ys zs :: [c]
    zs = (HasCallStack => [d]) -> [d]
    forall a. HasCallStack => (HasCallStack => a) -> a
    withFrozenCallStack ((HasCallStack => [d]) -> [d]) -> (HasCallStack => [d]) -> [d]
    forall a b. (a -> b) -> a -> b
    $ (String -> [d])
    -> [d] -> (a -> b -> c -> [d] -> [d]) -> [a] -> [b] -> [c] -> [d]
    forall r a b c.
    HasCallStack =>
    (String -> r)
    -> r -> (a -> b -> c -> r -> r) -> [a] -> [b] -> [c] -> r
    zipWith3Exact_ (String -> String -> String -> [d]
    forall a. HasCallStack => String -> String -> String -> a
    addNote "" "zipWith3Exact") [] (\a :: a
    a b :: b
    b c :: c
    c xs :: [d]
    xs -> a -> b -> c -> d
    f a
    a b
    b c
    c d -> [d] -> [d]
    forall a. a -> [a] -> [a]
    : [d]
    xs) [a]
    xs [b]
    ys [c]
    zs

    zip3ExactNote :: Partial => String -> [a] -> [b] -> [c]-> [(a,b,c)]
    zip3ExactNote :: String -> [a] -> [b] -> [c] -> [(a, b, c)]
    zip3ExactNote note :: String
    note xs :: [a]
    xs ys :: [b]
    ys zs :: [c]
    zs = (HasCallStack => [(a, b, c)]) -> [(a, b, c)]
    forall a. HasCallStack => (HasCallStack => a) -> a
    withFrozenCallStack ((HasCallStack => [(a, b, c)]) -> [(a, b, c)])
    -> (HasCallStack => [(a, b, c)]) -> [(a, b, c)]
    forall a b. (a -> b) -> a -> b
    $ (String -> [(a, b, c)])
    -> [(a, b, c)]
    -> (a -> b -> c -> [(a, b, c)] -> [(a, b, c)])
    -> [a]
    -> [b]
    -> [c]
    -> [(a, b, c)]
    forall r a b c.
    HasCallStack =>
    (String -> r)
    -> r -> (a -> b -> c -> r -> r) -> [a] -> [b] -> [c] -> r
    zipWith3Exact_ (String -> String -> String -> [(a, b, c)]
    forall a. HasCallStack => String -> String -> String -> a
    addNote String
    note "zip3ExactNote") [] (\a :: a
    a b :: b
    b c :: c
    c xs :: [(a, b, c)]
    xs -> (a
    a,b
    b,c
    c) (a, b, c) -> [(a, b, c)] -> [(a, b, c)]
    forall a. a -> [a] -> [a]
    : [(a, b, c)]
    xs) [a]
    xs [b]
    ys [c]
    zs

    zip3ExactMay :: [a] -> [b] -> [c] -> Maybe [(a,b,c)]
    zip3ExactMay :: [a] -> [b] -> [c] -> Maybe [(a, b, c)]
    zip3ExactMay = (String -> Maybe [(a, b, c)])
    -> Maybe [(a, b, c)]
    -> (a -> b -> c -> Maybe [(a, b, c)] -> Maybe [(a, b, c)])
    -> [a]
    -> [b]
    -> [c]
    -> Maybe [(a, b, c)]
    forall r a b c.
    HasCallStack =>
    (String -> r)
    -> r -> (a -> b -> c -> r -> r) -> [a] -> [b] -> [c] -> r
    zipWith3Exact_ (Maybe [(a, b, c)] -> String -> Maybe [(a, b, c)]
    forall a b. a -> b -> a
    const Maybe [(a, b, c)]
    forall a. Maybe a
    Nothing) ([(a, b, c)] -> Maybe [(a, b, c)]
    forall a. a -> Maybe a
    Just [])  (\a :: a
    a b :: b
    b c :: c
    c xs :: Maybe [(a, b, c)]
    xs -> ([(a, b, c)] -> [(a, b, c)])
    -> Maybe [(a, b, c)] -> Maybe [(a, b, c)]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ((a
    a,b
    b,c
    c) (a, b, c) -> [(a, b, c)] -> [(a, b, c)]
    forall a. a -> [a] -> [a]
    :) Maybe [(a, b, c)]
    xs)

    zip3ExactDef :: [(a,b,c)] -> [a] -> [b] -> [c] -> [(a,b,c)]
    zip3ExactDef :: [(a, b, c)] -> [a] -> [b] -> [c] -> [(a, b, c)]
    zip3ExactDef def :: [(a, b, c)]
    def = [(a, b, c)] -> Maybe [(a, b, c)] -> [(a, b, c)]
    forall a. a -> Maybe a -> a
    fromMaybe [(a, b, c)]
    def (Maybe [(a, b, c)] -> [(a, b, c)])
    -> ([a] -> [b] -> [c] -> Maybe [(a, b, c)])
    -> [a]
    -> [b]
    -> [c]
    -> [(a, b, c)]
    forall b c a1 a2 a3.
    HasCallStack =>
    (b -> c) -> (a1 -> a2 -> a3 -> b) -> a1 -> a2 -> a3 -> c
    .^^ [a] -> [b] -> [c] -> Maybe [(a, b, c)]
    forall a b c. [a] -> [b] -> [c] -> Maybe [(a, b, c)]
    zip3ExactMay

    zipWith3ExactNote :: Partial => String -> (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]
    zipWith3ExactNote :: String -> (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]
    zipWith3ExactNote note :: String
    note f :: a -> b -> c -> d
    f xs :: [a]
    xs ys :: [b]
    ys zs :: [c]
    zs = (HasCallStack => [d]) -> [d]
    forall a. HasCallStack => (HasCallStack => a) -> a
    withFrozenCallStack ((HasCallStack => [d]) -> [d]) -> (HasCallStack => [d]) -> [d]
    forall a b. (a -> b) -> a -> b
    $ (String -> [d])
    -> [d] -> (a -> b -> c -> [d] -> [d]) -> [a] -> [b] -> [c] -> [d]
    forall r a b c.
    HasCallStack =>
    (String -> r)
    -> r -> (a -> b -> c -> r -> r) -> [a] -> [b] -> [c] -> r
    zipWith3Exact_ (String -> String -> String -> [d]
    forall a. HasCallStack => String -> String -> String -> a
    addNote String
    note "zipWith3ExactNote") []  (\a :: a
    a b :: b
    b c :: c
    c xs :: [d]
    xs -> a -> b -> c -> d
    f a
    a b
    b c
    c d -> [d] -> [d]
    forall a. a -> [a] -> [a]
    : [d]
    xs) [a]
    xs [b]
    ys [c]
    zs

    zipWith3ExactMay :: (a -> b -> c -> d) -> [a] -> [b] -> [c] -> Maybe [d]
    zipWith3ExactMay :: (a -> b -> c -> d) -> [a] -> [b] -> [c] -> Maybe [d]
    zipWith3ExactMay f :: a -> b -> c -> d
    f = (String -> Maybe [d])
    -> Maybe [d]
    -> (a -> b -> c -> Maybe [d] -> Maybe [d])
    -> [a]
    -> [b]
    -> [c]
    -> Maybe [d]
    forall r a b c.
    HasCallStack =>
    (String -> r)
    -> r -> (a -> b -> c -> r -> r) -> [a] -> [b] -> [c] -> r
    zipWith3Exact_ (Maybe [d] -> String -> Maybe [d]
    forall a b. a -> b -> a
    const Maybe [d]
    forall a. Maybe a
    Nothing) ([d] -> Maybe [d]
    forall a. a -> Maybe a
    Just [])  (\a :: a
    a b :: b
    b c :: c
    c xs :: Maybe [d]
    xs -> ([d] -> [d]) -> Maybe [d] -> Maybe [d]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (a -> b -> c -> d
    f a
    a b
    b c
    c d -> [d] -> [d]
    forall a. a -> [a] -> [a]
    :) Maybe [d]
    xs)

    zipWith3ExactDef :: [d] -> (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]
    zipWith3ExactDef :: [d] -> (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]
    zipWith3ExactDef def :: [d]
    def = [d] -> Maybe [d] -> [d]
    forall a. a -> Maybe a -> a
    fromMaybe [d]
    def (Maybe [d] -> [d])
    -> ((a -> b -> c -> d) -> [a] -> [b] -> [c] -> Maybe [d])
    -> (a -> b -> c -> d)
    -> [a]
    -> [b]
    -> [c]
    -> [d]
    forall b c a1 a2 a3 a4.
    HasCallStack =>
    (b -> c)
    -> (a1 -> a2 -> a3 -> a4 -> b) -> a1 -> a2 -> a3 -> a4 -> c
    .^^^ (a -> b -> c -> d) -> [a] -> [b] -> [c] -> Maybe [d]
    forall a b c d.
    (a -> b -> c -> d) -> [a] -> [b] -> [c] -> Maybe [d]
    zipWith3ExactMay