{-# LANGUAGE Safe, MultiParamTypeClasses, FlexibleInstances #-}

{- |
    Module      :  SDP.Scan
    Copyright   :  (c) Andrey Mulik 2019
    License     :  BSD-style
    Maintainer  :  work.a.mulik@gmail.com
    Portability :  non-portable (requires non-portable modules)
    
    "SDP.Scan" provides 'Scan' - class for overloaded scans. 'Scan' needed for
    generalization and not so useful is practice as other @sdp@ classes.
-}
module SDP.Scan ( Scan (..) ) where

import Prelude ()
import SDP.SafePrelude
import SDP.Linear

import qualified Data.List as L ( scanl, scanr, scanl', scanl1, scanr1 )

default ()

--------------------------------------------------------------------------------

-- | Scan is class of scans.
class (Linear s a) => Scan s a
  where
    scanl,  scanl' :: (b -> a -> b) -> b -> s -> [b]
    scanr,  scanr' :: (a -> b -> b) -> b -> s -> [b]
    scanl1, scanr1 :: (a -> a -> a) -> s -> [a]
    
    scanl  b -> a -> b
f b
base = (b -> a -> b) -> b -> [a] -> [b]
forall s a b. Scan s a => (b -> a -> b) -> b -> s -> [b]
scanl  b -> a -> b
f b
base ([a] -> [b]) -> (s -> [a]) -> s -> [b]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. s -> [a]
forall l e. Linear l e => l -> [e]
listL
    scanr  a -> b -> b
f b
base = (a -> b -> b) -> b -> [a] -> [b]
forall s a b. Scan s a => (a -> b -> b) -> b -> s -> [b]
scanr  a -> b -> b
f b
base ([a] -> [b]) -> (s -> [a]) -> s -> [b]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. s -> [a]
forall l e. Linear l e => l -> [e]
listL
    scanl' b -> a -> b
f b
base = (b -> a -> b) -> b -> [a] -> [b]
forall s a b. Scan s a => (b -> a -> b) -> b -> s -> [b]
scanl' b -> a -> b
f b
base ([a] -> [b]) -> (s -> [a]) -> s -> [b]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. s -> [a]
forall l e. Linear l e => l -> [e]
listL
    scanr' a -> b -> b
f b
base = (a -> b -> b) -> b -> [a] -> [b]
forall s a b. Scan s a => (a -> b -> b) -> b -> s -> [b]
scanr' a -> b -> b
f b
base ([a] -> [b]) -> (s -> [a]) -> s -> [b]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. s -> [a]
forall l e. Linear l e => l -> [e]
listL
    
    scanl1 a -> a -> a
f = (a -> a -> a) -> [a] -> [a]
forall s a. Scan s a => (a -> a -> a) -> s -> [a]
scanl1 a -> a -> a
f ([a] -> [a]) -> (s -> [a]) -> s -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. s -> [a]
forall l e. Linear l e => l -> [e]
listL
    scanr1 a -> a -> a
f = (a -> a -> a) -> [a] -> [a]
forall s a. Scan s a => (a -> a -> a) -> s -> [a]
scanr1 a -> a -> a
f ([a] -> [a]) -> (s -> [a]) -> s -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. s -> [a]
forall l e. Linear l e => l -> [e]
listL

--------------------------------------------------------------------------------

instance Scan [a] a
  where
    scanl :: (b -> a -> b) -> b -> [a] -> [b]
scanl  = (b -> a -> b) -> b -> [a] -> [b]
forall b a. (b -> a -> b) -> b -> [a] -> [b]
L.scanl
    scanr :: (a -> b -> b) -> b -> [a] -> [b]
scanr  = (a -> b -> b) -> b -> [a] -> [b]
forall a b. (a -> b -> b) -> b -> [a] -> [b]
L.scanr
    scanl' :: (b -> a -> b) -> b -> [a] -> [b]
scanl' = (b -> a -> b) -> b -> [a] -> [b]
forall b a. (b -> a -> b) -> b -> [a] -> [b]
L.scanl'
    scanr' :: (a -> b -> b) -> b -> [a] -> [b]
scanr' = (a -> b -> b) -> b -> [a] -> [b]
forall a b. (a -> b -> b) -> b -> [a] -> [b]
L.scanr
    scanl1 :: (a -> a -> a) -> [a] -> [a]
scanl1 = (a -> a -> a) -> [a] -> [a]
forall a. (a -> a -> a) -> [a] -> [a]
L.scanl1
    scanr1 :: (a -> a -> a) -> [a] -> [a]
scanr1 = (a -> a -> a) -> [a] -> [a]
forall a. (a -> a -> a) -> [a] -> [a]
L.scanr1