This module imprements a Point-Free library using Formal Methods approach.
See Mpi.hs or CP.hs from http://www.di.uminho.pt/
\begin{code}
module Music.Analysis.PF where
import Data.Maybe (Maybe(..), maybe)
import Data.Either (Either(..), either)
import Data.Bool (Bool)
import Data.Tuple (uncurry, curry, fst, snd)
import Data.Function ((.), ($), id, const)
import Data.List ((++))
import Prelude ()
infix 5 ><
infix 4 -|-
\end{code}
\begin{code}
split :: (a -> b) -> (a -> c) -> a -> (b,c)
split f g x = (f x, g x)
(><) :: (a -> b) -> (c -> d) -> (a,c) -> (b,d)
f >< g = split (f . p1) (g . p2)
(!) :: a -> ()
(!) = const ()
\end{code}
\begin{code}
p1 :: (a, b) -> a
p1 = fst
p2 :: (a, b) -> b
p2 = snd
\end{code}
\begin{code}
i1 :: a -> Either a b
i1 = Left
i2 :: b -> Either a b
i2 = Right
(-|-) :: (a -> b) -> (c -> d) -> Either a c -> Either b d
f -|- g = either (i1 . f) (i2 . g)
cond :: (b -> Bool) -> (b -> c) -> (b -> c) -> b -> c
cond p f g = (either f g) . (grd p)
\end{code}
\begin{code}
ap :: (a -> b,a) -> b
ap = uncurry ($)
expn :: (b -> c) -> (a -> b) -> a -> c
expn f = curry (f . ap)
\end{code}
\begin{code}
grd :: (a -> Bool) -> a -> Either a a
grd p x = if p x then Left x else Right x
\end{code}
\begin{code}
swap :: (a,b) -> (b,a)
swap = split snd fst
assocr :: ((a,b),c) -> (a,(b,c))
assocr = split ( fst . fst ) (split ( snd . fst ) snd )
assocl :: (a,(b,c)) -> ((a,b),c)
assocl = split ( id >< p1 ) ( p2 . p2 )
distr :: (a,Either b c) -> Either (a,b) (a,c)
distr (a, Left b) = i1 (a, b)
distr (a, Right c) = i2 (a, c)
undistr :: Either (a,b) (a,c) -> (a,Either b c)
undistr = either ( id >< i1 ) ( id >< i2 )
flatr :: (a,(b,c)) -> (a,b,c)
flatr (a,(b,c)) = (a,b,c)
flatl :: ((a,b),c) -> (a,b,c)
flatl ((b,c),d) = (b,c,d)
unflatr :: (a,b,c) -> (a,(b,c))
unflatr (a,b,c) = (a,(b,c))
unflatl :: (a,b,c) -> ((a,b),c)
unflatl (b,c,d) = ((b,c),d)
pwnil :: a -> (a,())
pwnil = split id (!)
coswap :: Either a b -> Either b a
coswap = either i2 i1
coassocr :: Either (Either a b) c -> Either a (Either b c)
coassocr = either (id -|- i1) (i2 . i2)
\end{code}
\begin{code}
maybe2either :: Maybe a -> Either () a
maybe2either Nothing = Left ()
maybe2either (Just v) = Right v
either2maybe :: Either () a -> Maybe a
either2maybe (Left ()) = Nothing
either2maybe (Right a) = Just a
e2m :: Either () a -> Maybe a
e2m = either2maybe
m2e :: Maybe a -> Either () a
m2e = maybe2either
\end{code}
\begin{code}
outL :: [a] -> Maybe (a, [a])
outL [] = Nothing
outL (h:t) = Just (h,t)
cataL :: (Maybe (a, c) -> c) -> [a] -> c
cataL g = g . e2m . (id -|- id >< cataL g) . m2e . outL
inL :: Maybe (a, [a]) -> [a]
inL Nothing = []
inL (Just v) = uncurry (:) v
anaL :: (c -> Maybe (a, c)) -> c -> [a]
anaL g = inL . e2m . (id -|- id >< anaL g) . m2e . g
hyloL :: (Maybe (c, b) -> b) -> (a -> Maybe (c, a)) -> a -> b
hyloL g h = g . e2m . (id -|- id >< hyloL g h) . m2e . h
\end{code}
\begin{code}
mapL :: (a -> b) -> [a] -> [b]
mapL f = cataL (maybe [] (uncurry (:) . (f >< id)))
concatL :: [[a]] -> [a]
concatL = cataL (maybe [] (uncurry (++)))
reverseL :: [a] -> [a]
reverseL = cataL (maybe [] (uncurry (++) . swap . ((:[]). id >< id)))
\end{code}
\begin{code}
outL1 :: [a] -> Maybe (Either a (a, [a]))
outL1 [] = Nothing
outL1 [x] = Just (i1 x)
outL1 (h:t) = Just (i2 (h,t))
cataL1 :: (Maybe (Either a (a, c)) -> c) -> [a] -> c
cataL1 g = g . e2m . (id -|- (id -|- id >< cataL1 g)) . m2e . outL1
inL1 :: Maybe (Either a (a, [a])) -> [a]
inL1 Nothing = []
inL1 (Just v) = either (:[]) (uncurry (:)) v
anaL1 :: (c -> Maybe (Either a (a, c))) -> c -> [a]
anaL1 g = inL1 . e2m . (id -|- (id -|- id >< anaL1 g)) . m2e . g
hyloL1 :: (Maybe (Either d (c, b)) -> b) -> (a -> Maybe (Either d (c, a))) -> a -> b
hyloL1 g h = g . e2m . (id -|- (id -|- id >< hyloL1 g h)) . m2e . h
\end{code}