step-function-0.2: Staircase functions or piecewise constant functions

Safe HaskellSafe
LanguageHaskell2010

Data.Function.Step

Contents

Synopsis

Step Function

Examples

>>> let heaviside = step 0 (-1) 1 :: SF Int Int
>>> putSF heaviside
\x -> if
    | x < 0     -> -1
    | otherwise -> 1
>>> map (heaviside !) [-3, 0, 4]
[-1,1,1]

data SF k v Source #

Step function. Piecewise constant function, having finitely many pieces. See https://en.wikipedia.org/wiki/Step_function.

SF (fromList [(Open k1, v1), (Closed k2, v2)]) v3 :: SF k v describes a piecewise constant function \(f : k \to v\):

\[ f\,x = \begin{cases} v_1, \quad x < k_1 \newline v_2, \quad k_1 \le x \le k_2 \newline v_3, \quad k_2 < x \end{cases} \]

or as you would write in Haskell

f x | x <  k1   = v1
    | x <= k2   = v2
    | otherwise = v3

Note: total-map package, which provides function with finite support.

Constructor is exposed as you cannot construct non-valid SF.

Merging

You can use Applicative instance to merge SF.

>>> putSF $ liftA2 (+) (step 0 0 1) (step 1 0 1)
\x -> if
    | x < 0     -> 0
    | x < 1     -> 1
    | otherwise -> 2

Following property holds, i.e. SF and ordinary function Applicative instances are compatible (and ! is a homomorphism).

liftA2 f g h ! x == liftA2 f (g !) (h !) x

Recall that for ordinary functions liftA2 f g h x = f (g x) (h x).

Dense?

This dense variant is useful with dense ordered domains, e.g. Rational. Integer is not dense, so you could use Data.Function.Step.Discrete variant instead.

>>> let s = fromList [(Open 0, -1),(Closed 0, 0)] 1 :: SF Rational Int
>>> putSF s
\x -> if
    | x <  0 % 1 -> -1
    | x <= 0 % 1 -> 0
    | otherwise  -> 1
>>> import Data.Ratio ((%))
>>> map (s !) [-1, -0.5, 0, 0.5, 1]
[-1,-1,0,1,1]

Constructors

SF !(Map (Bound k) v) !v 

Instances

Show2 SF Source # 

Methods

liftShowsPrec2 :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> (Int -> b -> ShowS) -> ([b] -> ShowS) -> Int -> SF a b -> ShowS #

liftShowList2 :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> (Int -> b -> ShowS) -> ([b] -> ShowS) -> [SF a b] -> ShowS #

Ord k => Monad (SF k) Source # 

Methods

(>>=) :: SF k a -> (a -> SF k b) -> SF k b #

(>>) :: SF k a -> SF k b -> SF k b #

return :: a -> SF k a #

fail :: String -> SF k a #

Functor (SF k) Source # 

Methods

fmap :: (a -> b) -> SF k a -> SF k b #

(<$) :: a -> SF k b -> SF k a #

Ord k => Applicative (SF k) Source #

pure is a constant function.

Methods

pure :: a -> SF k a #

(<*>) :: SF k (a -> b) -> SF k a -> SF k b #

liftA2 :: (a -> b -> c) -> SF k a -> SF k b -> SF k c #

(*>) :: SF k a -> SF k b -> SF k b #

(<*) :: SF k a -> SF k b -> SF k a #

Foldable (SF k) Source # 

Methods

fold :: Monoid m => SF k m -> m #

foldMap :: Monoid m => (a -> m) -> SF k a -> m #

foldr :: (a -> b -> b) -> b -> SF k a -> b #

foldr' :: (a -> b -> b) -> b -> SF k a -> b #

foldl :: (b -> a -> b) -> b -> SF k a -> b #

foldl' :: (b -> a -> b) -> b -> SF k a -> b #

foldr1 :: (a -> a -> a) -> SF k a -> a #

foldl1 :: (a -> a -> a) -> SF k a -> a #

toList :: SF k a -> [a] #

null :: SF k a -> Bool #

length :: SF k a -> Int #

elem :: Eq a => a -> SF k a -> Bool #

maximum :: Ord a => SF k a -> a #

minimum :: Ord a => SF k a -> a #

sum :: Num a => SF k a -> a #

product :: Num a => SF k a -> a #

Traversable (SF k) Source # 

Methods

traverse :: Applicative f => (a -> f b) -> SF k a -> f (SF k b) #

sequenceA :: Applicative f => SF k (f a) -> f (SF k a) #

mapM :: Monad m => (a -> m b) -> SF k a -> m (SF k b) #

sequence :: Monad m => SF k (m a) -> m (SF k a) #

Show k => Show1 (SF k) Source # 

Methods

liftShowsPrec :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> Int -> SF k a -> ShowS #

liftShowList :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> [SF k a] -> ShowS #

(Eq v, Eq k) => Eq (SF k v) Source # 

Methods

(==) :: SF k v -> SF k v -> Bool #

(/=) :: SF k v -> SF k v -> Bool #

(Ord v, Ord k) => Ord (SF k v) Source # 

Methods

compare :: SF k v -> SF k v -> Ordering #

(<) :: SF k v -> SF k v -> Bool #

(<=) :: SF k v -> SF k v -> Bool #

(>) :: SF k v -> SF k v -> Bool #

(>=) :: SF k v -> SF k v -> Bool #

max :: SF k v -> SF k v -> SF k v #

min :: SF k v -> SF k v -> SF k v #

(Show k, Show v) => Show (SF k v) Source # 

Methods

showsPrec :: Int -> SF k v -> ShowS #

show :: SF k v -> String #

showList :: [SF k v] -> ShowS #

(Ord k, Semigroup v) => Semigroup (SF k v) Source #

Piecewise <>.

>>> putSF $ step 0 "a" "b" <> step 1 "c" "d"
\x -> if
    | x < 0     -> "ac"
    | x < 1     -> "bc"
    | otherwise -> "bd"

Methods

(<>) :: SF k v -> SF k v -> SF k v #

sconcat :: NonEmpty (SF k v) -> SF k v #

stimes :: Integral b => b -> SF k v -> SF k v #

(Ord k, Monoid v) => Monoid (SF k v) Source # 

Methods

mempty :: SF k v #

mappend :: SF k v -> SF k v -> SF k v #

mconcat :: [SF k v] -> SF k v #

(Ord k, Arbitrary k, Arbitrary v) => Arbitrary (SF k v) Source # 

Methods

arbitrary :: Gen (SF k v) #

shrink :: SF k v -> [SF k v] #

(NFData k, NFData v) => NFData (SF k v) Source # 

Methods

rnf :: SF k v -> () #

data Bound k Source #

Bound operations

Constructors

Open k

less-than, <

Closed k

less-than-or-equal, .

Instances

Functor Bound Source # 

Methods

fmap :: (a -> b) -> Bound a -> Bound b #

(<$) :: a -> Bound b -> Bound a #

Foldable Bound Source # 

Methods

fold :: Monoid m => Bound m -> m #

foldMap :: Monoid m => (a -> m) -> Bound a -> m #

foldr :: (a -> b -> b) -> b -> Bound a -> b #

foldr' :: (a -> b -> b) -> b -> Bound a -> b #

foldl :: (b -> a -> b) -> b -> Bound a -> b #

foldl' :: (b -> a -> b) -> b -> Bound a -> b #

foldr1 :: (a -> a -> a) -> Bound a -> a #

foldl1 :: (a -> a -> a) -> Bound a -> a #

toList :: Bound a -> [a] #

null :: Bound a -> Bool #

length :: Bound a -> Int #

elem :: Eq a => a -> Bound a -> Bool #

maximum :: Ord a => Bound a -> a #

minimum :: Ord a => Bound a -> a #

sum :: Num a => Bound a -> a #

product :: Num a => Bound a -> a #

Traversable Bound Source # 

Methods

traverse :: Applicative f => (a -> f b) -> Bound a -> f (Bound b) #

sequenceA :: Applicative f => Bound (f a) -> f (Bound a) #

mapM :: Monad m => (a -> m b) -> Bound a -> m (Bound b) #

sequence :: Monad m => Bound (m a) -> m (Bound a) #

Show1 Bound Source # 

Methods

liftShowsPrec :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> Int -> Bound a -> ShowS #

liftShowList :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> [Bound a] -> ShowS #

Eq k => Eq (Bound k) Source # 

Methods

(==) :: Bound k -> Bound k -> Bool #

(/=) :: Bound k -> Bound k -> Bool #

Ord k => Ord (Bound k) Source #

Order is like Open k = (k, False), Closed k = (k, True).

Methods

compare :: Bound k -> Bound k -> Ordering #

(<) :: Bound k -> Bound k -> Bool #

(<=) :: Bound k -> Bound k -> Bool #

(>) :: Bound k -> Bound k -> Bool #

(>=) :: Bound k -> Bound k -> Bool #

max :: Bound k -> Bound k -> Bound k #

min :: Bound k -> Bound k -> Bound k #

Show k => Show (Bound k) Source # 

Methods

showsPrec :: Int -> Bound k -> ShowS #

show :: Bound k -> String #

showList :: [Bound k] -> ShowS #

Arbitrary k => Arbitrary (Bound k) Source # 

Methods

arbitrary :: Gen (Bound k) #

shrink :: Bound k -> [Bound k] #

NFData k => NFData (Bound k) Source # 

Methods

rnf :: Bound k -> () #

Construction

constant :: a -> SF k a Source #

Constant function

>>> putSF $ constant 1
\_ -> 1

step :: k -> v -> v -> SF k v Source #

Step function.

step k v1 v2 = \ x -> if x < k then v1 else v2.

>>> putSF $ step 1 2 3
\x -> if
    | x < 1     -> 2
    | otherwise -> 3

fromList :: Ord k => [(Bound k, v)] -> v -> SF k v Source #

Create function from list of cases and default value.

>>> let f = fromList [(Open 1,2),(Closed 3,4),(Open 4,5)] 6
>>> putSF f
\x -> if
    | x <  1    -> 2
    | x <= 3    -> 4
    | x <  4    -> 5
    | otherwise -> 6
>>> map (f !) [0..10]
[2,4,4,4,6,6,6,6,6,6,6]

Normalisation

normalise :: Eq v => SF k v -> SF k v Source #

Merge adjustent pieces with same values.

Note: SF isn't normalised on construction. Values don't necessarily are Eq.

>>> putSF $ normalise heaviside
\x -> if
    | x < 0     -> -1
    | otherwise -> 1
>>> putSF $ normalise $ step 0 1 1
\_ -> 1
normalise (liftA2 (+) p (fmap negate p)) == (pure 0 :: SF Int Int)

Operators

(!) :: Ord k => SF k v -> k -> v infixl 9 Source #

Apply SF.

>>> heaviside ! 2
1

values :: SF k v -> [v] Source #

Possible values of SF

>>> values heaviside
[-1,1]

Debug

showSF :: (Show a, Show b) => SF a b -> String Source #

Show SF as Haskell code

putSF :: (Show a, Show b) => SF a b -> IO () Source #