Clean 0.3 → 0.4
raw patch · 13 files changed
+289/−116 lines, 13 files
Files
- Clean.cabal +2/−2
- src/Clean.hs +7/−5
- src/Clean/Applicative.hs +15/−9
- src/Clean/Arrow.hs +46/−15
- src/Clean/Classes.hs +1/−3
- src/Clean/Core.hs +124/−9
- src/Clean/Foldable.hs +1/−2
- src/Clean/Functor.hs +38/−7
- src/Clean/Lens.hs +3/−0
- src/Clean/Monad.hs +32/−8
- src/Clean/Monoid.hs +0/−32
- src/Clean/Traversable.hs +20/−9
- src/Clean/Unit.hs +0/−15
Clean.cabal view
@@ -1,5 +1,5 @@ name: Clean-version: 0.3+version: 0.4 synopsis: A light, clean and powerful utility library description: A collection of the most useful stuff I've found cleaned up and bundled in one convenient location@@ -14,7 +14,7 @@ library hs-source-dirs: src- exposed-modules: Clean Clean.Monoid Clean.Functor Clean.Monad Clean.Arrow Clean.Applicative Clean.Foldable Clean.Traversable Clean.Lens Clean.Unit Clean.Core+ exposed-modules: Clean Clean.Core Clean.Functor Clean.Applicative Clean.Monad Clean.Arrow Clean.Foldable Clean.Traversable Clean.Lens other-modules: Clean.Classes build-depends: base ==4.6.*, containers ghc-options: -W
src/Clean.hs view
@@ -1,11 +1,13 @@ module Clean( module Clean.Monad,- module Clean.Applicative,+ module Clean.Foldable,+ module Clean.Traversable,+ module Clean.Arrow, module Clean.Core,- module Clean.Monoid ) where import Clean.Monad-import Clean.Applicative-import Clean.Core-import Clean.Monoid+import Clean.Foldable+import Clean.Traversable+import Clean.Arrow+import Clean.Core hiding (flip)
src/Clean/Applicative.hs view
@@ -1,7 +1,7 @@-{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleContexts,FlexibleInstances #-} -- |A module describing applicative functors module Clean.Applicative(- module Clean.Functor,module Clean.Unit,+ module Clean.Functor, Applicative(..), ZipList(..),ZipTree(..),Backwards(..),@@ -9,10 +9,8 @@ (*>),(<*),ap ) where -import Clean.Monoid import Clean.Functor import Clean.Classes-import Clean.Unit import Clean.Core import Data.Tree import Clean.Foldable@@ -30,15 +28,22 @@ instance Applicative Tree instance Monad Tree where join (Node (Node a subs) subs') = Node a (subs + map join subs')+instance (Applicative f,Applicative g) => Applicative (Compose f g) where+ Compose fs <*> Compose xs = Compose ((<*>)<$>fs<*>xs)+deriving instance Unit Interleave+instance Applicative Interleave+instance Monad Interleave where join = fold + {-| A wrapper type for lists with zipping Applicative instances, such that @ZipList [f1,...,fn] '<*>' ZipList [x1,...,xn] == ZipList [f1 x1,...,fn xn]@ -} newtype ZipList a = ZipList { getZipList :: [a] }-instance Nil a => Nil (ZipList a) where zero = pure zero-instance Monoid a => Monoid (ZipList a) where+instance Semigroup a => Semigroup (ZipList a) where a + b = (+)<$>a<*>b+instance Monoid a => Monoid (ZipList a) where zero = pure zero+ instance Functor ZipList where map f (ZipList l) = ZipList (map f l) instance Unit ZipList where@@ -61,14 +66,15 @@ ZipTree (Node (f x) (getZipList ((<*>)<$>ZipList fs<*>ZipList xs))) deriving instance Foldable ZipTree --- |A wrapper for Applicative functors with action executed in the reverse order+-- |A wrapper for applicative functors with actions executed in the reverse order newtype Backwards f a = Backwards { forwards :: f a }-deriving instance Nil (f a) => Nil (Backwards f a)+deriving instance Semigroup (f a) => Semigroup (Backwards f a) deriving instance Monoid (f a) => Monoid (Backwards f a)+deriving instance Ring (f a) => Ring (Backwards f a) deriving instance Unit f => Unit (Backwards f) deriving instance Functor f => Functor (Backwards f) instance Applicative f => Applicative (Backwards f) where- Backwards fs <*> Backwards xs = Backwards (map (flip ($)) xs <*> fs)+ Backwards fs <*> Backwards xs = Backwards (map (&) xs <*> fs) ap = (<*>) a *> b = flip const<$>a<*>b
src/Clean/Arrow.hs view
@@ -1,30 +1,61 @@-{-# LANGUAGE DefaultSignatures #-}-module Clean.Arrow where+{-# LANGUAGE DefaultSignatures, TupleSections #-}+module Clean.Arrow (+ Arrow(..),+ (>>>),(<<<),(>>^),(^>>),(|||), -import Clean.Category+ Apply(..),app,++ Kleisli(..)+ ) where++import Clean.Core hiding (flip)+import Clean.Classes import Clean.Monad-import Clean.Core+import Clean.Traversable+import Clean.Lens -class Split ar => Arrow ar where- arr :: (a -> b) -> ar a b+(>>>) = flip (.)+(<<<) = (.)+(^>>) = promap+(>>^) = (<&>)+infixr 4 >>>,<<<,^>>,>>^++class (Split k,Choice k) => Arrow k where+ arr :: (a -> b) -> k a b instance Arrow (->) where arr = id+class Arrow k => Apply k where+ apply :: k (k a b,a) b+instance Apply (->) where apply (f,x) = f x+instance Arrow k => Cofunctor (Flip k a) where+ comap f (Flip g) = Flip (arr f >>> g)+app f = arr (f,) >>> apply -class Profunctor p where- promap :: (a -> b) -> p b c -> p a c- default promap :: Arrow p => (a -> b) -> p b c -> p a c- promap f = (arr f >>>) -infixr 4 $>>-($>>) = promap+a ||| b = (Left<$>a) <|> (Right<$>b) -a ||| b = (a >>> arr Left) <|> (b >>> arr Right)+instance (Monad f,Contravariant f,Monad g) => Monad (Compose f g) where+ join = map getCompose >>> getCompose >>> map collect+ >>> join >>> map join >>> Compose +kc = iso (Compose . runKleisli) (Kleisli . getCompose)+kc' = iso (Kleisli . getCompose) (Compose . runKleisli) newtype Kleisli m a b = Kleisli { runKleisli :: a -> m b }+instance Unit m => Unit (Kleisli m a) where pure = Kleisli . const . pure +instance Functor f => Functor (Kleisli f a) where map f m = m ^. kc.lam (map f).kc'+instance Monad m => Applicative (Kleisli m a)+instance Monad m => Monad (Kleisli m a) where join m = m ^. kc.lam (join . map (^.kc)).kc'+ instance Monad m => Category (Kleisli m) where id = Kleisli pure Kleisli f . Kleisli g = Kleisli (\a -> g a >>= f) instance Monad m => Choice (Kleisli m) where Kleisli f <|> Kleisli g = Kleisli (f <|> g)-instance (Monad m,Applicative m) => Split (Kleisli m) where+instance Monad m => Split (Kleisli m) where Kleisli f <#> Kleisli g = Kleisli (\(a,c) -> (,)<$>f a<*>g c)-instance (Monad m,Applicative m) => Arrow (Kleisli m) where+instance Monad m => Apply (Kleisli m) where+ apply = Kleisli (\(Kleisli f,a) -> f a)+instance Monad m => Arrow (Kleisli m) where arr a = Kleisli (pure . a)++++
src/Clean/Classes.hs view
@@ -2,7 +2,6 @@ module Clean.Classes where import Clean.Core-import Clean.Unit class Functor f where map :: (a -> b) -> f a -> f b@@ -18,5 +17,4 @@ (>>=) :: m a -> (a -> m b) -> m b ma >>= k = join (map k ma) infixl 1 >>=- - +
src/Clean/Core.hs view
@@ -1,9 +1,28 @@-{-# LANGUAGE NoRebindableSyntax #-}+{-# LANGUAGE NoRebindableSyntax, MultiParamTypeClasses, FlexibleInstances, DefaultSignatures, TupleSections #-} module Clean.Core(- Category(..),Choice(..),Split(..),(:*:),(:+:),+ -- * Basic union and product types+ (:*:),(:+:), - first,second,left,right,ifThenElse,fail,- + -- * Basic group and ring structure+ -- ** Classes+ Semigroup(..),SubSemi(..),Monoid(..),Ring(..),+ Unit(..),++ -- ** Common monoids+ Endo(..),Dual(..),OrdList(..),Interleave(..),++ -- * Fundamental control operations+ Category(..),+ Choice(..),Split(..),++ -- * Misc functions+ const,(&),++ first,second,left,right,++ ifThenElse,guard,fail,++ -- * The rest is imported from the Prelude module Prelude ) where @@ -11,16 +30,74 @@ Functor(..),Monad(..), sequence,mapM,mapM_,sequence_,(=<<), - map,(++),filter,length,sum,- (+),(.),id)+ map,(++),foldl,foldr,concat,filter,length,sum,+ (+),(*),(.),id,const) import qualified Prelude as P--ifThenElse b th el = if b then th else el-fail = error+import Data.Tree+import qualified Data.Set as S type a:*:b = (a,b) type a:+:b = Either a b +{-|+The class of all types that have a binary operation. Note that the operation+isn't necesarily commutative (in the case of lists, for example)+-} +class Semigroup m where+ (+) :: m -> m -> m+ default (+) :: Num m => m -> m -> m+ (+) = (P.+)+instance Semigroup () where _+_ = ()+instance Semigroup Bool where (+) = (||)+instance Semigroup Int+instance Semigroup Float+instance Semigroup Integer+instance Ord a => Semigroup (S.Set a) where (+) = S.union+instance Semigroup [a] where []+l = l ; (x:t)+l = x:(t+l)+instance (Semigroup a,Semigroup b) => Semigroup (a:*:b) where (a,b)+(c,d) = (a+c,b+d)+instance SubSemi b a => Semigroup (a:+:b) where+ Left a+Left b = Left (a+b)+ a+b = Right (from a+from b)+ where from = to <|> id++-- |A monoid is a semigroup with a null element such that @zero + a == a + zero == a@+class Semigroup m => Monoid m where+ zero :: m+ default zero :: Num m => m+ zero = 0+instance Monoid () where zero = ()+instance Monoid Int ; instance Monoid Integer ; instance Monoid Float+instance Ord a => Monoid (S.Set a) where zero = S.empty+instance Monoid [a] where zero = []+instance (Monoid a,Monoid b) => Monoid (a:*:b) where zero = (zero,zero)+instance (SubSemi b a,Monoid a) => Monoid (a:+:b) where zero = Left zero+instance Monoid Bool where zero = False++class (Semigroup a,Semigroup b) => SubSemi a b where+ to :: b -> a+instance Monoid a => SubSemi a () where to _ = zero++class Monoid m => Ring m where+ one :: m+ default one :: Num m => m+ one = 1+ (*) :: m -> m -> m+ default (*) :: Num m => m -> m -> m+ (*) = (P.*)+instance Ring Bool where one = True ; (*) = (&&)+instance Ring Int+instance Ring Integer+instance Ring Float++class Unit f where+ pure :: a -> f a+instance Unit (Either a) where pure = Right+instance Monoid w => Unit ((,) w) where pure a = (zero,a)+instance Unit ((->) b) where pure = P.const+instance Unit [] where pure a = [a]+instance Unit Tree where pure a = Node a []+instance Unit IO where pure = P.return+ class Category k where id :: k a a (.) :: k b c -> k a b -> k a c@@ -39,7 +116,45 @@ (<#>) :: k a c -> k b d -> k (a,b) (c,d) instance Split (->) where f <#> g = \(a,b) -> (f a,g b) +{-| A monoid on category endomorphisms under composition -}+newtype Endo k a = Endo { runEndo :: k a a }+instance Category k => Semigroup (Endo k a) where Endo f+Endo g = Endo (f . g)+instance Category k => Monoid (Endo k a) where zero = Endo id++{-| The dual of a monoid is the same as the original, with arguments reversed -}+newtype Dual m = Dual { getDual :: m }+instance Semigroup m => Semigroup (Dual m) where Dual a+Dual b = Dual (b+a)+deriving instance Monoid m => Monoid (Dual m)+instance Ring m => Ring (Dual m) where + one = Dual one+ Dual a * Dual b = Dual (b*a)++-- |An ordered list+newtype OrdList a = OrdList { getOrdList :: [a] }+instance Ord a => Semigroup (OrdList a) where+ OrdList a + OrdList b = OrdList (merge a b)+ where merge xs@(x:xt) ys@(y:yt) | x<y = x:merge xt ys+ | otherwise = y:merge xs yt+ merge a b = a+b+deriving instance Ord a => Monoid (OrdList a)+deriving instance Unit OrdList++newtype Interleave a = Interleave { interleave :: [a] }+instance Semigroup (Interleave a) where+ Interleave as + Interleave bs = Interleave (inter as bs)+ where inter (a:as) bs = a:inter bs as+ inter [] bs = bs+deriving instance Monoid (Interleave a)++(&) = flip ($)+ second a = id <#> a first a = a <#> id left a = a <|> id right a = id <|> a++guard p = if p then pure () else zero++ifThenElse b th el = if b then th else el+fail = error+const = pure
src/Clean/Foldable.hs view
@@ -2,8 +2,6 @@ module Clean.Foldable where import Clean.Core-import Clean.Monoid-import Clean.Unit import Clean.Classes import Clean.Functor import Data.Tree@@ -16,6 +14,7 @@ instance Foldable [] where fold [] = zero fold (x:t) = x+fold t+deriving instance Foldable Interleave instance Foldable Tree where fold (Node m subs) = m + fold (map fold subs) foldMap f e = fold (map f e)
src/Clean/Functor.hs view
@@ -1,23 +1,37 @@+{-# LANGUAGE FlexibleInstances #-} -- |A module for functors-module Clean.Functor(Functor(..),Id(..),Const(..),(<$>),(<$),(<&>),void) where+module Clean.Functor(+ Functor(..),Cofunctor(..),+ + Id(..),Const(..),Flip(..),Compose(..), + (<$>),(<$),(<&>),void,+ promap+ ) where+ import qualified Prelude as P -import Clean.Category import Clean.Classes-import Clean.Monoid-import Clean.Unit import Clean.Core import Data.Tree +class Cofunctor f where+ comap :: (a -> b) -> f b -> f a+instance Cofunctor (Flip (->) r) where+ comap f (Flip g) = Flip (g . f)+instance (Functor f,Cofunctor g) => Cofunctor (Compose f g) where+ comap f (Compose c) = Compose (map (comap f) c)+promap f c = unFlip (comap f (Flip c))+ instance Functor [] where map f = f' where f' [] = [] ; f' (x:t) = f x:f' t instance Functor Tree where map f (Node a subs) = Node (f a) (map (map f) subs) -- |The Identity Functor newtype Id a = Id { getId :: a }-deriving instance Nil a => Nil (Id a)+deriving instance Semigroup a => Semigroup (Id a) deriving instance Monoid w => Monoid (Id w)+deriving instance Ring w => Ring (Id w) instance Unit Id where pure = Id instance Functor Id instance Applicative Id@@ -25,16 +39,33 @@ -- |The Constant Functor newtype Const a b = Const { getConst :: a }-deriving instance Nil a => Nil (Const a b)-deriving instance Monoid w => Monoid (Const w a)+deriving instance Semigroup w => Semigroup (Const w a)+deriving instance Monoid a => Monoid (Const a b) instance Unit (Const a) where pure _ = Const undefined instance Functor (Const a) instance Applicative (Const a) instance Monad (Const a) where Const a >>= _ = Const a +-- |A motherflippin' functor+newtype Flip f a b = Flip { unFlip :: f b a }++-- |The Composition functor+newtype Compose f g a = Compose { getCompose :: f (g a) }+instance (Unit f,Unit g) => Unit (Compose f g) where pure = Compose . pure . pure+instance (Functor f,Functor g) => Functor (Compose f g) where+ map f (Compose c) = Compose (map (map f) c)++newtype Product f g a = Product { getProduct :: f a:*:g a }+instance (Functor f,Functor g) => Functor (Product f g) where+ map f = Product . (map f <#> map f) . getProduct+newtype Sum f g a = Sum { getSum :: f a:+:g a }+instance (Functor f,Functor g) => Functor (Sum f g) where+ map f = Sum . (Left<$>map f <|> Right<$>map f) . getSum+ instance Functor (Either b) where map f = Left <|> Right . f instance Functor ((,) b) where map f (b,a) = (b,f a) instance Functor ((->) a) where map = (.)+deriving instance Functor Interleave instance Functor IO instance Applicative IO
src/Clean/Lens.hs view
@@ -4,6 +4,7 @@ import Clean.Core import Clean.Functor import Clean.Applicative+import Clean.Foldable type LensLike f s t a b = (s -> f t) -> (a -> f b) type LensLike' f a b = LensLike f b b a a@@ -16,8 +17,10 @@ iso f g = lens f (const g) iso' :: (a -> b) -> (b -> a) -> Lens' a b iso' = iso+lam f = lens f const (^.) :: a -> Lens' a b -> b+infixl 2 ^. x^.l = getConst (l Const x) type Traversal s t a b = forall f. Applicative f => LensLike f s t a b
src/Clean/Monad.hs view
@@ -1,21 +1,26 @@ {-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, TupleSections, Rank2Types #-} module Clean.Monad( module Clean.Applicative,+ Monad(..),MonadFix(..),MonadTrans(..),+ MonadState(..), MonadReader(..),MonadWriter(..),+ StateT(..),State,- ReaderT(..),WriterT(..),+ ReaderT(..),Reader,WriterT(..),Writer,+ ContT(..),Cont,+ (=<<),(>>),return ) where import Clean.Classes import Clean.Applicative-import Clean.Core-import Clean.Monoid+import Clean.Core hiding (flip)+import Clean.Traversable class MonadFix m where- fix :: (a -> m a) -> m a+ mfix :: (a -> m a) -> m a class Monad m => MonadState s m where get :: m s put :: s -> m ()@@ -40,7 +45,12 @@ listen_ = internal (\m -> listen m<&> \(w,(c,a)) -> (c,(w,a))) censor_ = internal (\m -> censor (m<&> \(c,(a,f)) -> ((c,a),f))) -{- A simple State Monad -}+fix f = f (fix f)+cfix f = map fix (collect f) +instance MonadFix Id where mfix = cfix+instance MonadFix ((->) b) where mfix = cfix++{-| A simple State Monad -} newtype StateT s m a = StateT { runStateT :: s -> m (s,a) } type State s a = StateT s Id a instance Unit m => Unit (StateT s m) where pure a = StateT (\s -> pure (s,a))@@ -59,9 +69,10 @@ ask = ask_ ; local = local_ instance MonadWriter w m => MonadWriter w (StateT s m) where tell = tell_ ; listen = listen_ ; censor = censor_--{- A simple Reader monad -}+ +{-| A simple Reader monad -} newtype ReaderT r m a = ReaderT { runReaderT :: r -> m a }+type Reader r a = ReaderT r Id a instance MonadTrans (ReaderT r) where lift m = ReaderT (const m) internal f (ReaderT r) = ReaderT (map snd . f . map ((),) . r)@@ -78,8 +89,9 @@ instance MonadWriter w m => MonadWriter w (ReaderT r m) where tell = tell_ ; listen = listen_ ; censor = censor_ -{- A simple Writer monad -}+{-| A simple Writer monad -} newtype WriterT w m a = WriterT { runWriterT :: m (w,a) }+type Writer w a = WriterT w Id a instance Monoid w => MonadTrans (WriterT w) where lift m = WriterT (map (zero,) m) internal f (WriterT m) = WriterT (f m)@@ -98,6 +110,18 @@ ask = ask_ ; local = local_ instance (Monoid w,MonadState r m) => MonadState r (WriterT w m) where get = get_ ; put = put_ ; modify = modify_++{-| A simple continuation monad implementation -}+newtype ContT r m a = ContT { runContT :: (a -> m r) -> m r }+type Cont r a = ContT r Id a+instance Unit m => Unit (ContT r m) where pure a = ContT ($a)+instance Monad m => Functor (ContT r m)+instance Monad m => Applicative (ContT r m)+instance Monad m => Monad (ContT r m) where+ ContT k >>= f = ContT (\cc -> k (\a -> runContT (f a) cc))+instance MonadTrans (ContT r) where+ lift m = ContT (m >>=)+ internal _ (ContT _) = undefined (>>) = (*>) (=<<) = flip (>>=)
− src/Clean/Monoid.hs
@@ -1,32 +0,0 @@-{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}-module Clean.Monoid where--import qualified Prelude as P-import Clean.Core--class Nil z where- zero :: z-instance Nil () where zero = ()-instance Nil Int where zero = 0-instance Nil [a] where zero = []-instance (Nil a,Nil b) => Nil (a:*:b) where zero = (zero,zero)-instance Nil a => Nil (a:+:b) where zero = Left zero--class Nil m => Monoid m where- (+) :: m -> m -> m-instance Monoid () where _+_ = ()-instance Monoid Int where (+) = (P.+)-instance Monoid [a] where []+l = l ; (x:t)+l = x:(t+l)-instance (Monoid a,Monoid b) => Monoid (a:*:b) where (a,b)+(c,d) = (a+c,b+d)-instance Submonoid b a => Monoid (a:+:b) where- Left a+Left b = Left (a+b)- a+b = Right (from a+from b)- where from = to <|> id--class (Monoid a,Monoid b) => Submonoid a b where- to :: b -> a-instance Monoid a => Submonoid a () where to _ = zero--newtype Endo k a = Endo { runEndo :: k a a }-instance Category k => Nil (Endo k a) where zero = Endo id-instance Category k => Monoid (Endo k a) where Endo f+Endo g = Endo (f . g)
src/Clean/Traversable.hs view
@@ -1,21 +1,21 @@+{-# LANGUAGE FlexibleInstances #-} module Clean.Traversable(- module Clean.Foldable,module Clean.Applicative,+ module Clean.Applicative, - Traversable(..),+ Traversable(..),Contravariant(..), - traverse,foreach,transpose+ traverse,foreach,transpose,flip ) where import Clean.Classes-import Clean.Core-import Clean.Foldable+import Clean.Core hiding (flip,(&)) import Clean.Applicative import Data.Tree -class Foldable t => Traversable t where+class Traversable t where sequence :: Applicative f => t (f a) -> f (t a) instance Traversable (Either a) where- sequence = pure . Left <|> map Right + sequence = pure . Left <|> map Right instance Traversable [] where sequence (x:xs) = (:)<$>x<*>sequence xs sequence [] = pure []@@ -24,8 +24,19 @@ sequence (Node a subs) = Node<$>a<*>sequence (map sequence subs) deriving instance Traversable ZipTree +class Contravariant t where+ collect :: Functor f => f (t a) -> t (f a)+instance Contravariant Id where collect f = Id (map getId f)+instance Contravariant ((->) a) where collect f = \a -> map ($a) f+instance (Applicative f,Contravariant f,Semigroup m) => Semigroup (f m) where+ fa + fb = (+)<$>fa<*>fb+instance (Applicative f,Contravariant f,Monoid m) => Monoid (f m) where+ zero = pure zero+instance (Applicative f,Contravariant f,Ring r) => Ring (f r) where+ one = pure one+ fa * fb = (*)<$>fa<*>fb+ traverse f t = sequence (map f t) foreach = flip traverse transpose = sequence--+flip = collect
− src/Clean/Unit.hs
@@ -1,15 +0,0 @@-module Clean.Unit where--import qualified Prelude as P-import Clean.Core-import Clean.Monoid-import Data.Tree--class Unit f where- pure :: a -> f a-instance Unit (Either a) where pure = Right-instance Monoid w => Unit ((,) w) where pure a = (zero,a)-instance Unit ((->) b) where pure = const-instance Unit [] where pure a = [a]-instance Unit Tree where pure a = Node a []-instance Unit IO where pure = P.return