module Ideas.Common.Classes
(
Apply(applyAll), apply, applicable, applyD, applyM, applyList
, Container(singleton, getSingleton)
, BiArrow(..)
, BiFunctor(biMap, mapFirst, mapSecond), mapBoth
, Fix(..)
, Buggy(..), Minor(..)
) where
import Control.Arrow
import Data.Maybe
import qualified Data.Set as S
class Apply t where
applyAll :: t a -> a -> [a]
apply :: Apply t => t a -> a -> Maybe a
apply ta = listToMaybe . applyAll ta
applicable :: Apply t => t a -> a -> Bool
applicable ta = isJust . apply ta
applyD :: Apply t => t a -> a -> a
applyD ta a = fromMaybe a (apply ta a)
applyM :: (Apply t, Monad m) => t a -> a -> m a
applyM ta = maybe (fail "applyM") return . apply ta
applyList :: Apply t => [t a] -> a -> Maybe a
applyList xs a = foldl (\m r -> m >>= applyM r) (Just a) xs
class Container f where
singleton :: a -> f a
getSingleton :: f a -> Maybe a
instance Container [] where
singleton = return
getSingleton [a] = Just a
getSingleton _ = Nothing
instance Container S.Set where
singleton = S.singleton
getSingleton = getSingleton . S.toList
infix 1 <->
class Arrow arr => BiArrow arr where
(<->) :: (a -> b) -> (b -> a) -> arr a b
(!->) :: (a -> b) -> arr a b
(<-!) :: (b -> a) -> arr a b
(!->) f = f <-> errBiArrow
(<-!) f = errBiArrow <-> f
errBiArrow :: a
errBiArrow = error "BiArrow: not bi-directional"
class BiFunctor f where
biMap :: (a -> c) -> (b -> d) -> f a b -> f c d
mapFirst :: (a -> b) -> f a c -> f b c
mapSecond :: (b -> c) -> f a b -> f a c
mapFirst = flip biMap id
mapSecond = biMap id
instance BiFunctor Either where
biMap f g = either (Left . f) (Right . g)
instance BiFunctor (,) where
biMap f g (a, b) = (f a, g b)
mapBoth :: BiFunctor f => (a -> b) -> f a a -> f b b
mapBoth f = biMap f f
class Fix a where
fix :: (a -> a) -> a
fix f = let a = f a in a
class Buggy a where
buggy :: a -> a
setBuggy :: Bool -> a -> a
isBuggy :: a -> Bool
buggy = setBuggy True
class Minor a where
minor :: a -> a
setMinor :: Bool -> a -> a
isMinor :: a -> Bool
isMajor :: a -> Bool
minor = setMinor True
isMajor = not . isMinor