{-# 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 :: forall a. Partial => String -> String -> String -> a
addNote String
note String
fun String
msg = String -> a
forall a. Partial => String -> a
error (String -> a) -> String -> a
forall a b. (a -> b) -> a -> b
$
    String
"Safe.Exact." String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
fun String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
", " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
msg String -> String -> String
forall a. [a] -> [a] -> [a]
++ (if String -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
note then String
"" else String
", " 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_ :: forall r a.
Partial =>
(String -> r) -> ([a] -> r) -> (a -> r -> r) -> Int -> [a] -> r
splitAtExact_ String -> r
err [a] -> r
nil a -> r -> r
cons Int
o [a]
xs
    | Int
o Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 = String -> r
err (String -> r) -> String -> r
forall a b. (a -> b) -> a -> b
$ String
"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 Int
0 [a]
xs = [a] -> r
nil [a]
xs
        f Int
i (a
x:[a]
xs) = a
x a -> r -> r
`cons` Int -> [a] -> r
f (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) [a]
xs
        f Int
i [] = String -> r
err (String -> r) -> String -> r
forall a b. (a -> b) -> a -> b
$ String
"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]
++ String
", 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_ :: forall r a b.
Partial =>
(String -> r) -> r -> (a -> b -> r -> r) -> [a] -> [b] -> r
zipWithExact_ String -> r
err r
nil a -> b -> r -> r
cons = [a] -> [b] -> r
f
    where
        f :: [a] -> [b] -> r
f (a
x:[a]
xs) (b
y:[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 [] [b]
_ = String -> r
err String
"second list is longer than the first"
        f [a]
_ [] = String -> r
err String
"first list is longer than the second"


{-# INLINE zipWith3Exact_ #-}
zipWith3Exact_ :: Partial => (String -> r) -> r -> (a -> b -> c -> r -> r) -> [a] -> [b] -> [c] -> r
zipWith3Exact_ :: forall r a b c.
Partial =>
(String -> r)
-> r -> (a -> b -> c -> r -> r) -> [a] -> [b] -> [c] -> r
zipWith3Exact_ String -> r
err r
nil a -> b -> c -> r -> r
cons = [a] -> [b] -> [c] -> r
f
    where
        f :: [a] -> [b] -> [c] -> r
f (a
x:[a]
xs) (b
y:[b]
ys) (c
z:[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 [] [b]
_ [c]
_ = String -> r
err String
"first list is shorter than the others"
        f [a]
_ [] [c]
_ = String -> r
err String
"second list is shorter than the others"
        f [a]
_ [b]
_ [] = String -> r
err String
"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 :: forall a. Partial => Int -> [a] -> [a]
takeExact Int
i [a]
xs = (Partial => [a]) -> [a]
forall a. Partial => (Partial => a) -> a
withFrozenCallStack ((Partial => [a]) -> [a]) -> (Partial => [a]) -> [a]
forall a b. (a -> b) -> a -> b
$ (String -> [a])
-> ([a] -> [a]) -> (a -> [a] -> [a]) -> Int -> [a] -> [a]
forall r a.
Partial =>
(String -> r) -> ([a] -> r) -> (a -> r -> r) -> Int -> [a] -> r
splitAtExact_ (String -> String -> String -> [a]
forall a. Partial => String -> String -> String -> a
addNote String
"" String
"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 :: forall a. Partial => Int -> [a] -> [a]
dropExact Int
i [a]
xs = (Partial => [a]) -> [a]
forall a. Partial => (Partial => a) -> a
withFrozenCallStack ((Partial => [a]) -> [a]) -> (Partial => [a]) -> [a]
forall a b. (a -> b) -> a -> b
$ (String -> [a])
-> ([a] -> [a]) -> (a -> [a] -> [a]) -> Int -> [a] -> [a]
forall r a.
Partial =>
(String -> r) -> ([a] -> r) -> (a -> r -> r) -> Int -> [a] -> r
splitAtExact_ (String -> String -> String -> [a]
forall a. Partial => String -> String -> String -> a
addNote String
"" String
"dropExact") [a] -> [a]
forall a. a -> a
id (\a
_ [a]
x -> [a]
x) 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 :: forall a. Partial => Int -> [a] -> ([a], [a])
splitAtExact Int
i [a]
xs = (Partial => ([a], [a])) -> ([a], [a])
forall a. Partial => (Partial => a) -> a
withFrozenCallStack ((Partial => ([a], [a])) -> ([a], [a]))
-> (Partial => ([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.
Partial =>
(String -> r) -> ([a] -> r) -> (a -> r -> r) -> Int -> [a] -> r
splitAtExact_ (String -> String -> String -> ([a], [a])
forall a. Partial => String -> String -> String -> a
addNote String
"" String
"splitAtExact")
    ([],) (\a
a ([a], [a])
b -> ([a] -> [a]) -> ([a], [a]) -> ([a], [a])
forall b c d. (b -> c) -> (b, d) -> (c, d)
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 :: forall a. Partial => String -> Int -> [a] -> [a]
takeExactNote String
note Int
i [a]
xs = (Partial => [a]) -> [a]
forall a. Partial => (Partial => a) -> a
withFrozenCallStack ((Partial => [a]) -> [a]) -> (Partial => [a]) -> [a]
forall a b. (a -> b) -> a -> b
$ (String -> [a])
-> ([a] -> [a]) -> (a -> [a] -> [a]) -> Int -> [a] -> [a]
forall r a.
Partial =>
(String -> r) -> ([a] -> r) -> (a -> r -> r) -> Int -> [a] -> r
splitAtExact_ (String -> String -> String -> [a]
forall a. Partial => String -> String -> String -> a
addNote String
note String
"takeExactNote") ([a] -> [a] -> [a]
forall a b. a -> b -> a
const []) (:) Int
i [a]
xs

takeExactMay :: Int -> [a] -> Maybe [a]
takeExactMay :: forall a. Int -> [a] -> Maybe [a]
takeExactMay = (String -> Maybe [a])
-> ([a] -> Maybe [a])
-> (a -> Maybe [a] -> Maybe [a])
-> Int
-> [a]
-> Maybe [a]
forall r a.
Partial =>
(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]) -> Maybe [a] -> Maybe [a]
forall a b. (a -> b) -> Maybe a -> Maybe b
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 :: forall a. [a] -> Int -> [a] -> [a]
takeExactDef [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.
Partial =>
(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 :: forall a. Partial => String -> Int -> [a] -> [a]
dropExactNote String
note Int
i [a]
xs = (Partial => [a]) -> [a]
forall a. Partial => (Partial => a) -> a
withFrozenCallStack ((Partial => [a]) -> [a]) -> (Partial => [a]) -> [a]
forall a b. (a -> b) -> a -> b
$ (String -> [a])
-> ([a] -> [a]) -> (a -> [a] -> [a]) -> Int -> [a] -> [a]
forall r a.
Partial =>
(String -> r) -> ([a] -> r) -> (a -> r -> r) -> Int -> [a] -> r
splitAtExact_ (String -> String -> String -> [a]
forall a. Partial => String -> String -> String -> a
addNote String
note String
"dropExactNote") [a] -> [a]
forall a. a -> a
id (\a
_ [a]
x -> [a]
x) Int
i [a]
xs

dropExactMay :: Int -> [a] -> Maybe [a]
dropExactMay :: forall a. Int -> [a] -> Maybe [a]
dropExactMay = (String -> Maybe [a])
-> ([a] -> Maybe [a])
-> (a -> Maybe [a] -> Maybe [a])
-> Int
-> [a]
-> Maybe [a]
forall r a.
Partial =>
(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 (\a
_ Maybe [a]
x -> Maybe [a]
x)

dropExactDef :: [a] -> Int -> [a] -> [a]
dropExactDef :: forall a. [a] -> Int -> [a] -> [a]
dropExactDef [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.
Partial =>
(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 :: forall a. Partial => String -> Int -> [a] -> ([a], [a])
splitAtExactNote String
note Int
i [a]
xs = (Partial => ([a], [a])) -> ([a], [a])
forall a. Partial => (Partial => a) -> a
withFrozenCallStack ((Partial => ([a], [a])) -> ([a], [a]))
-> (Partial => ([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.
Partial =>
(String -> r) -> ([a] -> r) -> (a -> r -> r) -> Int -> [a] -> r
splitAtExact_ (String -> String -> String -> ([a], [a])
forall a. Partial => String -> String -> String -> a
addNote String
note String
"splitAtExactNote")
    ([],) (\a
a ([a], [a])
b -> ([a] -> [a]) -> ([a], [a]) -> ([a], [a])
forall b c d. (b -> c) -> (b, d) -> (c, d)
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 :: forall a. 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.
Partial =>
(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)
    (\[a]
x -> ([a], [a]) -> Maybe ([a], [a])
forall a. a -> Maybe a
Just ([], [a]
x)) (\a
a Maybe ([a], [a])
b -> (([a], [a]) -> ([a], [a])) -> Maybe ([a], [a]) -> Maybe ([a], [a])
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (([a] -> [a]) -> ([a], [a]) -> ([a], [a])
forall b c d. (b -> c) -> (b, d) -> (c, d)
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 :: forall a. ([a], [a]) -> Int -> [a] -> ([a], [a])
splitAtExactDef ([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.
Partial =>
(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 :: forall a b. Partial => [a] -> [b] -> [(a, b)]
zipExact [a]
xs [b]
ys = (Partial => [(a, b)]) -> [(a, b)]
forall a. Partial => (Partial => a) -> a
withFrozenCallStack ((Partial => [(a, b)]) -> [(a, b)])
-> (Partial => [(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.
Partial =>
(String -> r) -> r -> (a -> b -> r -> r) -> [a] -> [b] -> r
zipWithExact_ (String -> String -> String -> [(a, b)]
forall a. Partial => String -> String -> String -> a
addNote String
"" String
"zipExact") []  (\a
a b
b [(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 :: forall a b c. Partial => (a -> b -> c) -> [a] -> [b] -> [c]
zipWithExact a -> b -> c
f [a]
xs [b]
ys = (Partial => [c]) -> [c]
forall a. Partial => (Partial => a) -> a
withFrozenCallStack ((Partial => [c]) -> [c]) -> (Partial => [c]) -> [c]
forall a b. (a -> b) -> a -> b
$ (String -> [c])
-> [c] -> (a -> b -> [c] -> [c]) -> [a] -> [b] -> [c]
forall r a b.
Partial =>
(String -> r) -> r -> (a -> b -> r -> r) -> [a] -> [b] -> r
zipWithExact_ (String -> String -> String -> [c]
forall a. Partial => String -> String -> String -> a
addNote String
"" String
"zipWithExact") [] (\a
a b
b [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 :: forall a b. Partial => String -> [a] -> [b] -> [(a, b)]
zipExactNote String
note [a]
xs [b]
ys = (Partial => [(a, b)]) -> [(a, b)]
forall a. Partial => (Partial => a) -> a
withFrozenCallStack ((Partial => [(a, b)]) -> [(a, b)])
-> (Partial => [(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.
Partial =>
(String -> r) -> r -> (a -> b -> r -> r) -> [a] -> [b] -> r
zipWithExact_ (String -> String -> String -> [(a, b)]
forall a. Partial => String -> String -> String -> a
addNote String
note String
"zipExactNote") []  (\a
a b
b [(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 :: forall a b. [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.
Partial =>
(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 b
b Maybe [(a, b)]
xs -> ([(a, b)] -> [(a, b)]) -> Maybe [(a, b)] -> Maybe [(a, b)]
forall a b. (a -> b) -> Maybe a -> Maybe 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 :: forall a b. [(a, b)] -> [a] -> [b] -> [(a, b)]
zipExactDef [(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.
Partial =>
(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 :: forall a b c.
Partial =>
String -> (a -> b -> c) -> [a] -> [b] -> [c]
zipWithExactNote String
note a -> b -> c
f [a]
xs [b]
ys = (Partial => [c]) -> [c]
forall a. Partial => (Partial => a) -> a
withFrozenCallStack ((Partial => [c]) -> [c]) -> (Partial => [c]) -> [c]
forall a b. (a -> b) -> a -> b
$ (String -> [c])
-> [c] -> (a -> b -> [c] -> [c]) -> [a] -> [b] -> [c]
forall r a b.
Partial =>
(String -> r) -> r -> (a -> b -> r -> r) -> [a] -> [b] -> r
zipWithExact_ (String -> String -> String -> [c]
forall a. Partial => String -> String -> String -> a
addNote String
note String
"zipWithExactNote") []  (\a
a b
b [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 :: forall a b c. (a -> b -> c) -> [a] -> [b] -> Maybe [c]
zipWithExactMay a -> b -> c
f = (String -> Maybe [c])
-> Maybe [c]
-> (a -> b -> Maybe [c] -> Maybe [c])
-> [a]
-> [b]
-> Maybe [c]
forall r a b.
Partial =>
(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 b
b Maybe [c]
xs -> ([c] -> [c]) -> Maybe [c] -> Maybe [c]
forall a b. (a -> b) -> Maybe a -> Maybe b
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 :: forall c a b. [c] -> (a -> b -> c) -> [a] -> [b] -> [c]
zipWithExactDef [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.
Partial =>
(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 :: forall a b c. Partial => [a] -> [b] -> [c] -> [(a, b, c)]
zip3Exact [a]
xs [b]
ys [c]
zs = (Partial => [(a, b, c)]) -> [(a, b, c)]
forall a. Partial => (Partial => a) -> a
withFrozenCallStack ((Partial => [(a, b, c)]) -> [(a, b, c)])
-> (Partial => [(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.
Partial =>
(String -> r)
-> r -> (a -> b -> c -> r -> r) -> [a] -> [b] -> [c] -> r
zipWith3Exact_ (String -> String -> String -> [(a, b, c)]
forall a. Partial => String -> String -> String -> a
addNote String
"" String
"zip3Exact") [] (\a
a b
b c
c [(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 :: forall a b c d.
Partial =>
(a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]
zipWith3Exact a -> b -> c -> d
f [a]
xs [b]
ys [c]
zs = (Partial => [d]) -> [d]
forall a. Partial => (Partial => a) -> a
withFrozenCallStack ((Partial => [d]) -> [d]) -> (Partial => [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.
Partial =>
(String -> r)
-> r -> (a -> b -> c -> r -> r) -> [a] -> [b] -> [c] -> r
zipWith3Exact_ (String -> String -> String -> [d]
forall a. Partial => String -> String -> String -> a
addNote String
"" String
"zipWith3Exact") [] (\a
a b
b c
c [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 :: forall a b c. Partial => String -> [a] -> [b] -> [c] -> [(a, b, c)]
zip3ExactNote String
note [a]
xs [b]
ys [c]
zs = (Partial => [(a, b, c)]) -> [(a, b, c)]
forall a. Partial => (Partial => a) -> a
withFrozenCallStack ((Partial => [(a, b, c)]) -> [(a, b, c)])
-> (Partial => [(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.
Partial =>
(String -> r)
-> r -> (a -> b -> c -> r -> r) -> [a] -> [b] -> [c] -> r
zipWith3Exact_ (String -> String -> String -> [(a, b, c)]
forall a. Partial => String -> String -> String -> a
addNote String
note String
"zip3ExactNote") [] (\a
a b
b c
c [(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 :: forall a b c. [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.
Partial =>
(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 b
b c
c Maybe [(a, b, c)]
xs -> ([(a, b, c)] -> [(a, b, c)])
-> Maybe [(a, b, c)] -> Maybe [(a, b, c)]
forall a b. (a -> b) -> Maybe a -> Maybe b
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 :: forall a b c. [(a, b, c)] -> [a] -> [b] -> [c] -> [(a, b, c)]
zip3ExactDef [(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.
Partial =>
(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 :: forall a b c d.
Partial =>
String -> (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]
zipWith3ExactNote String
note a -> b -> c -> d
f [a]
xs [b]
ys [c]
zs = (Partial => [d]) -> [d]
forall a. Partial => (Partial => a) -> a
withFrozenCallStack ((Partial => [d]) -> [d]) -> (Partial => [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.
Partial =>
(String -> r)
-> r -> (a -> b -> c -> r -> r) -> [a] -> [b] -> [c] -> r
zipWith3Exact_ (String -> String -> String -> [d]
forall a. Partial => String -> String -> String -> a
addNote String
note String
"zipWith3ExactNote") []  (\a
a b
b c
c [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 :: forall a b c d.
(a -> b -> c -> d) -> [a] -> [b] -> [c] -> Maybe [d]
zipWith3ExactMay 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.
Partial =>
(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 b
b c
c Maybe [d]
xs -> ([d] -> [d]) -> Maybe [d] -> Maybe [d]
forall a b. (a -> b) -> Maybe a -> Maybe b
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 :: forall d a b c.
[d] -> (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]
zipWith3ExactDef [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.
Partial =>
(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