data-foldapp (empty) → 0.1.0.0
raw patch · 8 files changed
+652/−0 lines, 8 filesdep +basedep +containerssetup-changed
Dependencies added: base, containers
Files
- ChangeLog.md +5/−0
- Data/FoldApp.hs +56/−0
- Data/FoldApp/Function.hs +302/−0
- Data/FoldApp/Generic.hs +152/−0
- Data/FoldApp/Identity.hs +65/−0
- LICENSE +30/−0
- Setup.hs +2/−0
- data-foldapp.cabal +40/−0
+ ChangeLog.md view
@@ -0,0 +1,5 @@+# Revision history for data-foldapp + +## 0.1.0.0 -- YYYY-mm-dd + +* First version. Released on an unsuspecting world.
+ Data/FoldApp.hs view
@@ -0,0 +1,56 @@+-- | This package provides a framework for constructing variadic+-- functions as folds over function applications.+--+-- For example, a variadic function @f@ may be reduced like this:+--+-- @+-- f a b c+-- ≡ foldlApp @(~) f' z a b c+-- ≡ f' (f' (f' z a) b) c+-- @+--+-- Both left and right associative folds are available.+--+-- This module re-exports "Data.FoldApp.Identity" which assumes the+-- identity conversion for arguments. "Data.FoldApp.Generic" provides+-- the generalised folds where a different converter may be given.+-- Conversion allows for folding over differently-typed arguments by+-- converting them to a common type.+--+-- "Data.FoldApp.Function" contains several variadic functions which+-- may be useful as examples or in your programs.+--+-- Folds cannot be defined to return functions. This is because the+-- parameters intended for the returned function become confused with+-- the parameters intended for folding. This weakness can be+-- circumvented by wrapping and unwrapping returned functions with+-- a newtype at the cost of inconvenience.+--+-- If a type inference problem arises, you possibly need to provide+-- an annotation for some arguments or an annotation for the return+-- type. For example, without any other typing context the following+-- is ambiguous …+--+-- @+-- listOf "hello" "sailor!"+-- @+--+-- … because it is not known how many more arguments should be+-- accepted. An annotation such as the following fixes this problem …+--+-- @+-- listOf "hello" "sailor!" :: String -> [String]+-- @+--+-- … saying one more @String@ argument must be given and a @[String]@+-- will be returned.+--+module Data.FoldApp+ ( module Data.FoldApp.Function+ , module Data.FoldApp.Identity+ )+where++import Data.FoldApp.Function++import Data.FoldApp.Identity
+ Data/FoldApp/Function.hs view
@@ -0,0 +1,302 @@+-- | Module of variadic functions.+--+-- All types used are re-exported.+--+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+module Data.FoldApp.Function+ ( Alternative+ , Bool+ , FoldlApp+ , FoldrApp+ , IntMap+ , IntSet+ , Map+ , MonadPlus+ , Monoid+ , NonEmpty+ , Num+ , Ord+ , Ordering+ , Seq+ , Set+ , allOf+ , allOfBy+ , asumOf+ , dualAsumOf+ , dualFoldOf+ , dualMsumOf+ , firstOf+ , foldOf+ , intSetOf+ , lastOf+ , lazyIntMapOf+ , lazyMapOf+ , listOf+ , maxOf+ , maxOfBy+ , minOf+ , minOfBy+ , msumOf+ , nonEmptyOf+ , productOf+ , reverseNonEmptyOf+ , reverseOf+ , reverseSeqOf+ , seqOf+ , setOf+ , strictIntMapOf+ , strictMapOf+ , sumOf+ )+where++import Control.Applicative+ ( Alternative(empty, (<|>))+ )+--++import Control.Monad+ ( MonadPlus(mzero, mplus)+ )+--++import Data.Bool+ ( Bool(True, False)+ , (||)+ , (&&)+ )+--++import Data.FoldApp.Identity+ ( FoldlApp+ , FoldrApp+ , foldlApp+ , foldrApp+ )+--++import Data.IntMap (IntMap)+import qualified Data.IntMap.Lazy as LazyIntMap+import qualified Data.IntMap.Strict as StrictIntMap++import Data.IntSet (IntSet)+import qualified Data.IntSet as IntSet++import Data.List.NonEmpty(NonEmpty((:|)))+import qualified Data.List.NonEmpty as NonEmpty++import Data.Map (Map)+import qualified Data.Map.Lazy as LazyMap+import qualified Data.Map.Strict as StrictMap++import Data.Monoid+ ( Monoid(mempty, mappend)+ )+--++import Data.Ord+ ( Ord+ , Ordering(LT, EQ, GT)+ )+--++import Data.Sequence (Seq)+import qualified Data.Sequence as Seq++import Data.Set(Set)+import qualified Data.Set as Set++import Prelude+ ( Num((+), (*))+ , (.)+ , flip+ , max+ , min+ , uncurry+ )+--++-- | True if all arguments are True, False otherwise.+--+allOf :: FoldrApp Bool Bool f => f+allOf = foldrApp (&&) True++-- | True if all arguments map to True, False otherwise.+--+allOfBy :: FoldlApp a Bool f => (a -> Bool) -> f+allOfBy f = foldlApp (\a x -> a && f x) True++-- | True if any arguments are True, False otherwise.+--+anyOf :: FoldrApp Bool Bool f => f+anyOf = foldrApp (||) False++-- | True if any arguments map to True, False otherwise.+--+anyOfBy :: FoldlApp a Bool f => (a -> Bool) -> f+anyOfBy f = foldlApp (\a x -> a || f x) False++-- | Concatentate all arguments with @\<|\>@.+--+asumOf :: forall a f g. (Alternative f, FoldrApp (f a) (f a) g) => g+asumOf = foldrApp (<|>) (empty :: f a)++-- | Concatenate all arguments with @\<|\>@ in reverse order.+--+dualAsumOf :: forall a f g. (Alternative f, FoldrApp (f a) (f a) g) => g+dualAsumOf = foldrApp (flip (<|>)) (empty :: f a)++-- | Concatenate all argments with @mappend@ in reverse order.+--+dualFoldOf :: forall a f. (Monoid a, FoldlApp a a f) => f+dualFoldOf = foldlApp (flip mappend) (mempty :: a)++-- | Concatenate all arguments with @mplus@ in reverse order.+--+dualMsumOf :: forall a m f. (MonadPlus m, FoldrApp (m a) (m a) f) => f+dualMsumOf = foldrApp (flip mplus) (mzero :: m a)++-- | Returns the first argument.+--+firstOf :: forall a f. FoldlApp a a f => a -> f+firstOf = foldlApp ((\x _ -> x) :: a -> a -> a)++-- | Concatenate all arguments with @mappend@.+--+foldOf :: forall a f. (Monoid a, FoldrApp a a f) => f+foldOf = foldrApp mappend (mempty :: a)++-- | Form an @IntSet@ from all arguments.+--+intSetOf :: forall f. FoldlApp IntSet.Key IntSet f => f+intSetOf = foldlApp (flip IntSet.insert) IntSet.empty++-- | Returns the last argument.+--+lastOf :: forall a f. FoldlApp a a f => a -> f+lastOf = foldlApp (\_ y -> y)++-- | Form a lazy @IntMap@ from all arguments.+--+lazyIntMapOf ::+ forall a f.+ FoldlApp (StrictIntMap.Key, a) (IntMap a) f =>+ f+lazyIntMapOf =+ foldlApp+ (flip (uncurry LazyIntMap.insert))+ (LazyIntMap.empty :: IntMap a)+--++-- | Form a lazy @Map@ from all arguments.+--+lazyMapOf :: forall k a f. (Ord k, FoldlApp (k, a) (Map k a) f) => f+lazyMapOf =+ foldlApp+ (flip (uncurry LazyMap.insert))+ (LazyMap.empty :: Map k a)+--++-- | Form a list from all arguments.+--+listOf :: forall a f. FoldrApp a [a] f => f+listOf = foldrApp (:) ([] :: [a])++-- | Return the largest argument.+--+maxOf :: forall a f. (Ord a, FoldlApp a a f) => a -> f+maxOf = foldlApp max++-- | Return the largest argument by the given comparator.+--+maxOfBy ::+ forall a f.+ (Ord a, FoldlApp a a f) =>+ (a -> a -> Ordering) -> a -> f+maxOfBy f = foldlApp (\a x -> case f a x of GT -> a; _ -> x)++-- | Return the smallest argument.+--+minOf :: forall a f. (Ord a, FoldlApp a a f) => a -> f+minOf = foldlApp min++-- | Return the smallest argument by the given comparator.+--+minOfBy ::+ forall a f.+ (Ord a, FoldlApp a a f) =>+ (a -> a -> Ordering) -> a -> f+minOfBy f = foldlApp (\a x -> case f a x of GT -> x; _ -> a)++-- | Concatentate all arguments with @mplus@.+--+msumOf :: forall a m f. (MonadPlus m, FoldrApp (m a) (m a) f) => f+msumOf = foldrApp mplus (mzero :: m a)++-- | Form a @NonEmpty@ list from all arguments.+--+nonEmptyOf :: FoldrApp a (NonEmpty a) f => a -> f+nonEmptyOf = foldrApp (\a (x:|xs) -> x:|(a:xs)) . (:|[])++-- | Return the product of all arguments.+--+productOf :: forall a f. (Num a, FoldlApp a a f) => f+productOf = foldlApp (*) (1 :: a)++-- | Form a @NonEmpty@ list in reverse order from all arguments.+--+reverseNonEmptyOf :: FoldlApp a (NonEmpty a) f => a -> f+reverseNonEmptyOf = foldlApp (\(x:|xs) a -> a:|(x:xs)) . (:|[])++-- | Form a list in reverse order from all arguments.+--+reverseOf :: forall a f. FoldlApp a [a] f => f+reverseOf = foldlApp (flip (:)) ([] :: [a])++-- | Form a @Seq@ from all arguments.+--+seqOf :: forall a f. FoldlApp a (Seq a) f => f+seqOf = foldlApp (Seq.|>) (Seq.empty :: Seq a)++-- | Form a @Seq@ in reverse order from all arguments.+--+reverseSeqOf :: forall a f. FoldlApp a (Seq a) f => f+reverseSeqOf = foldlApp (flip (Seq.<|)) (Seq.empty :: Seq a)++-- | Form a @Set@ from all arguments.+--+setOf :: forall a f. (Ord a, FoldlApp a (Set a) f) => f+setOf = foldlApp (flip Set.insert) (Set.empty :: Set a)++-- | Form a strict @IntMap@ from all arguments.+--+strictIntMapOf ::+ forall a f.+ FoldlApp (StrictIntMap.Key, a) (IntMap a) f =>+ f+strictIntMapOf =+ foldlApp+ (flip (uncurry StrictIntMap.insert))+ (StrictIntMap.empty :: IntMap a)+--++-- | Form a strict @Map@ from all arguments.+--+strictMapOf ::+ forall k a f.+ (Ord k, FoldlApp (k, a) (Map k a) f) =>+ f+strictMapOf =+ foldlApp+ (flip (uncurry StrictMap.insert))+ (StrictMap.empty :: Map k a)+--++-- | Return the sum of all arguments.+--+sumOf :: forall a f. (Num a, FoldlApp a a f) => f+sumOf = foldlApp (+) (0 :: a)
+ Data/FoldApp/Generic.hs view
@@ -0,0 +1,152 @@+-- | The most generic definitions for folding function applications.+--+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE KindSignatures #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE UndecidableSuperClasses #-}+module Data.FoldApp.Generic+ ( Converter(convert)+ , FoldlApp(foldlApp)+ , FoldrApp()+ , Monad+ , foldlMApp+ , foldrApp+ , foldrMApp+ )+where++import Control.Monad+ ( Monad((>>=), return)+ )+--++import Data.Kind+ ( Constraint+ )+--++import Prelude+ ( id+ , flip+ )+--++-- | Class of constraints which feature a function to convert a value of+-- one type to a value of another.+--+class Converter (conv :: * -> * -> Constraint) where+ convert :: conv a b => a -> b+--++instance Converter (~) where+ convert = id+--++-- | Constrain all parameters of f to be convertible to p and the return+-- of f to be r.+--+type family+ Infer (conv :: * -> * -> Constraint)+ (p :: * )+ (r :: * )+ (f :: * )+ :: Constraint+ where+ Infer conv p r (a -> f) = (conv a p, Infer conv p r f)+ Infer _ _ r s = r ~ s+--++-- | Class defining left-associative folds of function applications. No+-- other instances need be defined.+--+class+ ( Converter conv+ , Infer conv p r f+ ) =>+ FoldlApp (conv :: * -> * -> Constraint)+ (p :: * )+ (r :: * )+ (f :: * )+ where+ -- | Left-associative fold of function applications.+ foldlApp :: (r -> p -> r) -> r -> f+--++instance (Converter conv, Infer conv p r r) => FoldlApp conv p r r where+ foldlApp _ r = r+--++instance+ ( Converter conv+ , Infer conv p r (x -> f)+ , FoldlApp conv p r f+ ) =>+ FoldlApp conv p r (x -> f)+ where+ foldlApp f r p = foldlApp @conv f (f r (convert @conv p))+--++-- | Monadic left-associative fold of function applications.+--+foldlMApp ::+ forall conv m p r f.+ (Monad m, FoldlApp conv p (m r) f) =>+ (r -> p -> m r) -> r -> f+foldlMApp f r = foldlApp @conv (\r' p -> r' >>= flip f p) (return r)++-- | Class defining right-associative folds of function applications. No+-- other instances need be defined.+--+class+ ( Converter conv+ , Infer conv p r f+ ) =>+ FoldrApp (conv :: * -> * -> Constraint)+ (p :: * )+ (r :: * )+ (f :: * )+ where+ -- | Right-associative fold of function applications. This is an+ -- internal implementation; use 'foldrApp' instead.+ foldrAppImpl :: (p -> r -> r) -> (r -> r) -> r -> f+--++instance (Converter conv, Infer conv p r r) => FoldrApp conv p r r where+ foldrAppImpl _ g r = g r+--++instance+ ( Converter conv+ , Infer conv p r (x -> f)+ , FoldrApp conv p r f+ ) => FoldrApp conv p r (x -> f)+ where+ foldrAppImpl f g r p =+ foldrAppImpl @conv f (\r' -> g (f (convert @conv p) r')) r+--++-- | Right-associative fold of function applications.+--+foldrApp ::+ forall conv p r f.+ FoldrApp conv p r f =>+ (p -> r -> r) -> r -> f+foldrApp f = foldrAppImpl @conv f id++-- | Monadic right-associative fold of function applications.+--+foldrMApp ::+ forall conv m p r f.+ (Monad m, FoldrApp conv p (m r) f) =>+ (p -> r -> m r) -> r -> f+foldrMApp f r = foldrApp @conv (\p r' -> r' >>= f p) (return r)
+ Data/FoldApp/Identity.hs view
@@ -0,0 +1,65 @@+-- | Specialised functions for folds of function applications. The+-- converter has been specialised to the identity converter.+--+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TypeApplications #-}+module Data.FoldApp.Identity+ ( FoldlApp+ , FoldrApp+ , foldlApp+ , foldlMApp+ , foldrApp+ , foldrMApp+ , Monad+ )+where++import Control.Monad+ ( Monad+ )+--++import qualified Data.FoldApp.Generic as G++-- | @Data.FoldApp.FoldlApp@ with the identity converter chosen.+--+type FoldlApp p r f = G.FoldlApp (~) p r f++-- | @Data.FoldApp.FoldrAPp@ with the identity converter chosen.+--+type FoldrApp p r f = G.FoldrApp (~) p r f++-- | Left-associative fold of function applications.+--+foldlApp ::+ forall p r f.+ (FoldlApp p r f) =>+ (r -> p -> r) -> r -> f+foldlApp = G.foldlApp @(~)++-- | Monadic left-associative fold of function applications.+--+foldlMApp ::+ forall m p r f.+ (Monad m, FoldlApp p (m r) f) =>+ (r -> p -> m r) -> r -> f+foldlMApp = G.foldlMApp @(~)++-- | Right-associative fold of function applications.+--+foldrApp ::+ forall p r f.+ FoldrApp p r f =>+ (p -> r -> r) -> r -> f+foldrApp = G.foldrApp @(~)++-- | Monadic right-associative fold of function applications.+--+foldrMApp ::+ forall m p r f.+ (Monad m, FoldrApp p (m r) f) =>+ (p -> r -> m r) -> r -> f+foldrMApp = G.foldrMApp @(~)
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2017, Eric Brisco + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of Eric Brisco nor the names of other + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple +main = defaultMain
+ data-foldapp.cabal view
@@ -0,0 +1,40 @@+name: data-foldapp +version: 0.1.0.0 +synopsis: Fold function applications. Framework for variadic functions. +description: Fold function applications. Framework for variadic functions. +homepage: https://github.com/erisco/data-foldapp +license: BSD3 +license-file: LICENSE +author: Eric Brisco +maintainer: eric.brisco@gmail.com +copyright: Copyright (c) 2017, Eric Brisco +category: Data +build-type: Simple +extra-source-files: ChangeLog.md +cabal-version: >=1.10 + + + +source-repository head + type: git + location: https://github.com/erisco/data-foldapp + + + +source-repository this + type: git + location: https://github.com/erisco/data-foldapp + tag: v0.1.0.0 + + + +library + exposed-modules: Data.FoldApp + , Data.FoldApp.Generic + , Data.FoldApp.Identity + , Data.FoldApp.Function + + build-depends: base >=4.9 && <4.10 + , containers >=0.5 && <0.6 + + default-language: Haskell2010