{-
-- EPITECH PROJECT, 2026
-- My.hs
-- File description:
-- You know, I don t think there are good or bad descriptions,
-- for me, life is all about functions...
-}
mySucc :: Int -> Int
mySucc n = n + 1
myIsNeg :: Int -> Bool
myIsNeg n
| n < 0 = True
| otherwise = False
myAbs :: Int -> Int
myAbs n
| n < 0 = n * (-1)
| otherwise = n
myMin :: Int -> Int -> Int
myMin a b
| a < b = a
| otherwise = b
myMax :: Int -> Int -> Int
myMax a b
| a > b = a
| otherwise = b
myTuple :: a -> b -> (a , b)
myTuple a b = (a, b)
myTruple :: a -> b -> c -> (a , b , c)
myTruple a b c = (a, b, c)
myFst :: (a , b) -> a
myFst (n, _) = n
mySnd :: (a , b) -> b
mySnd (_, n) = n
mySwap :: (a , b) -> (b , a)
mySwap (a , b) = (b , a)
myHead :: [a] -> a
myHead [] = error "Empty list, can't return the head!"
myHead (h:_)= h
myTail :: [a] -> [a]
myTail [] = error "Empty list, can't return the tail!"
myTail (_:t) = t
myLength :: [a] -> Int
myLength [] = 0
myLength (_:t) = 1 + myLength t
myNth :: [a] -> Int -> a
myNth l n | n < 0 || n >= myLength l = error "Index out of range"
myNth l 0 = myHead l
myNth l n = myNth (myTail l) (n - 1)
myTake :: Int -> [a] -> [a]
myTake n l | n < 0 = error "Size out of range"
myTake 0 _ = []
myTake _ [] = []
myTake 1 (h:_) = [h]
myTake n (h:l) = h:myTake (n - 1) l
myDrop :: Int -> [a] -> [a]
myDrop n _ | n < 0 = error "Size out of range"
myDrop _ [] = []
myDrop 0 l = l
myDrop n l = myDrop (n - 1) (myTail l)
myAppend :: [a] -> [a] -> [a]
myAppend [] l = l
myAppend (h:l1) l2 = h:(myAppend l1 l2)
myReverse :: [a] -> [a]
myReverse [] = []
myReverse l = myNth l (myLength l - 1):myReverse (myTake (myLength l - 1) l)
myInit :: [a] -> [a]
myInit [] = error "Empty list, can't return the init!"
myInit l = myTake (myLength l - 1) l
myLast :: [a] -> a
myLast [] = error "Empty list, can't return the last!"
myLast l = myNth l (myLength l - 1)
myZip :: [a] -> [b] -> [(a , b)]
myZip [] _ = []
myZip _ [] = []
myZip (h1:l1) (h2:l2) = (h1, h2):(myZip l1 l2)
myUnzip :: [(a, b)] -> ([a], [b])
myUnzip [] = ([], [])
myUnzip ((a1, b1):l) = (a1:a2, b1:b2)
where (a2, b2) = myUnzip l
myMap :: (a -> b) -> [a] -> [b]
myMap _ [] = []
myMap func (h:l) = (func h):(myMap func l)
myFilter :: (a -> Bool) -> [a] -> [a]
myFilter _ [] = []
myFilter func (h:l)
| (func h) = h:(myFilter func l)
| otherwise = (myFilter func l)
myFoldl :: (b -> a -> b) -> b -> [a] -> b
myFoldl _ n [] = n
myFoldl func n (h:l) = (myFoldl func (func n h) l)
myFoldr :: (a -> b -> b) -> b -> [a] -> b
myFoldr _ n [] = n
myFoldr func n l = (myFoldr func (func (myLast l) n) (myInit l))
myPartition :: (a -> Bool) -> [a] -> ([a], [a])
myPartition _ [] = ([], [])
myPartition func (h:l)
| (func h) = (h:a, b)
| otherwise = (a, h:b)
where (a, b) = (myPartition func l)
myPartitionSort :: (a -> b -> Bool) -> b -> [a] -> ([a], [a])
myPartitionSort _ _ [] = ([], [])
myPartitionSort func v (h:l)
| (func h v) = (h:a, b)
| otherwise = (a, h:b)
where (a, b) = (myPartitionSort func v l)
myQuickSort :: (a -> a -> Bool) -> [a] -> [a]
myQuickSort _ [] = []
myQuickSort func l = (myAppend (myQuickSort func lt)
((myLast l): (myQuickSort func gt)))
where (lt, gt) = (myPartitionSort func (myLast l) (myInit l))