packages feed

polyvariadic (empty) → 0.3.0.0

raw patch · 6 files changed

+241/−0 lines, 6 filesdep +basedep +containersdep +semigroupssetup-changed

Dependencies added: base, containers, semigroups

Files

+ ChangeLog.md view
@@ -0,0 +1,6 @@+# Revision history for polyvariadic++## 0.3.0.0  -- 2017-04-19++* First public version.+
+ Data/Accumulator.hs view
@@ -0,0 +1,59 @@+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE CPP #-}++-- |+-- Module      :  Data.Accumulator+-- Copyright   :  (c) Francesco Gazzetta 2017+-- License     :  BSD3 (see the file LICENSE)+--+-- Maintainer  :  francygazz@gmail.org+-- Stability   :  stable+-- Portability :  portable+--+-- Accumulators, primarily useful for Polyvariadic++module Data.Accumulator+  ( Accumulator (..)+  , singleton+  , accumulateMany+  , AccumulatorSemigroup (..)+  ) where++import qualified Data.Set as Set+import           Data.Foldable (foldl')+import           Data.Semigroup++#if !MIN_VERSION_base(4,8,0)+import Data.Foldable+#endif++-- | An 'Accumulator c i' supports accumulation of elements of type i in it.+-- This is different from 'Semigroup' or 'Monoid', where '<>' acts between+-- two values with the same type.+class Accumulator acc x where+  accumulate :: x -> acc -> acc -- ^ Accumulate a value++-- | Accumulate a single value in a 'Monoid'+singleton :: (Accumulator acc x, Monoid acc) => x -> acc+singleton = flip accumulate mempty++-- | Strictly accumulate multiple values from a 'Foldable', from left to right+accumulateMany :: (Foldable f, Accumulator acc x) => f x -> acc -> acc+accumulateMany xs acc = foldl' (flip accumulate) acc xs++instance Accumulator [a] a where+  accumulate = (:)++instance Ord a => Accumulator (Set.Set a) a where+  accumulate = Set.insert++instance Semigroup m => Accumulator (AccumulatorSemigroup m) (AccumulatorSemigroup m) where+  accumulate = (<>)++-- | Lift a 'Semigroup' into an Accumulator. This is a newtype because (<>) isn't always the ideal way of accumulating+newtype AccumulatorSemigroup a = AccumulatorSemigroup {getAccumulatorSemigroup :: a}++instance Semigroup m => Semigroup (AccumulatorSemigroup m) where+  (<>) (AccumulatorSemigroup a) (AccumulatorSemigroup b) = AccumulatorSemigroup $ (<>) a b+
+ Data/Function/Polyvariadic.hs view
@@ -0,0 +1,110 @@+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE FlexibleInstances #-}++-- |+-- Module      :  Data.Function.Polyvariadic+-- Copyright   :  (c) Francesco Gazzetta 2017+-- License     :  BSD3 (see the file LICENSE)+--+-- Maintainer  :  francygazz@gmail.org+-- Stability   :  experimental+-- Portability :  portable+--+-- Create and apply functions with an arbitrary number of arguments.++module Data.Function.Polyvariadic+  ( -- * Creation+    Polyvariadic (..)+    -- * Application+  , Apply (apply')+  , apply+  ) where++import Data.Foldable+import Data.Accumulator+++---- creation++-- | Creation of functions with an arbitrary number of arguments.+--+-- The arguments will be accumulated in the given 'Accumulator',+-- which will then be passed as an argument to the function.+--+-- ==== __Examples__+--+-- Three integers to a list. Note that you have to add type annotations+-- for nearly everything to avoid ambiguities+-- >>> polyvariadic mempty (id :: [Int] -> [Int]) (1::Int) (2::Int) (3::Int) :: [Int]+--+-- The classic @printf@ function, which takes an arbitrary amount of arguments+-- and inserts them in a string:+--+-- @+-- {-# LANGUAGE MultiParamTypeClasses #-}+-- {-# LANGUAGE FlexibleInstances #-}+-- {-# LANGUAGE FlexibleContexts #-}+-- import Data.Function.Polyvariadic+-- import Data.Accumulator+--+-- magicChar = \'%\'+-- notMagicChar = (\/= magicChar)+--+-- data PrintfAccum = PrintfAccum { done :: String, todo :: String }+--+-- instance Show x => Accumulator PrintfAccum x where+--   accumulate x (PrintfAccum done (_:todo)) = PrintfAccum+--                                               (done ++ show x ++ takeWhile notMagicChar todo)+--                                               (dropWhile notMagicChar todo)+--   accumulate _ acc = acc+--+-- printf' str = polyvariadic+--                (PrintfAccum (takeWhile notMagicChar str) (dropWhile notMagicChar str))+--                done+-- @+--+-- >>> printf' "aaa%bbb%ccc%ddd" "TEST" 123 True+-- "aaa\"TEST\"bbb123cccTrueddd"+class Polyvariadic accumulator result x where+  -- | Takes an accumulator @acc@, a function @f@, and an arbitrary+  -- number of additional arguments which will be accumulated in @acc@,+  -- which is finally passed to @f@.+  polyvariadic :: accumulator -> (accumulator -> result) -> x++-- | Accumulates the next argument+instance (Accumulator c i, Polyvariadic c b x) => Polyvariadic c b (i -> x) where+  polyvariadic a f x = polyvariadic (accumulate x a) f++-- | There are no more arguments to accumulate so the function is applied+-- to the 'Accumulator'+instance Polyvariadic accumulator result result where+  polyvariadic a f = f a+++---- application++-- | Application of function with an arbitrary number of arguments to the+-- elements of a list.+--+-- __Will raise an error if the list doesn't have enough elements__+--+-- ==== __Examples__+--+-- >>> apply ((+) :: Int -> Int -> Int) ([1,2] :: [Int]) :: Int+-- 3+class Apply a b x where+  apply' :: x -> [a] -> b++-- | The final type is not reached yet and the application continues+instance (Apply a b x) => Apply a b (a -> x) where+  apply' f (x:xs) = apply (f x) xs+  apply' _ _ = error "Not enough arguments in polyvariadic application"++-- | The final type is reached and the application terminates+instance Apply a b b where+  apply' f _ = f++-- | Like 'apply'' but with an arbitrary 'Foldable' instead if a list+apply :: (Apply a b x, Foldable t) => x -> t a -> b+apply f = apply f . toList+
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2017, Francesco Gazzetta++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 Francesco Gazzetta 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
+ polyvariadic.cabal view
@@ -0,0 +1,34 @@+-- Initial polyvariadic.cabal generated by cabal init.  For further +-- documentation, see http://haskell.org/cabal/users-guide/++name:                polyvariadic+version:             0.3.0.0+synopsis:            Creation and application of polyvariadic functions+description:         Creation and application of polyvariadic functions, see the docs for usage and examples+homepage:            https://github.com/fgaz/polyvariadic+license:             BSD3+license-file:        LICENSE+author:              Francesco Gazzetta+maintainer:          francygazz@gmail.com+copyright:           (C) Francesco Gazzetta 2017+category:            Data+build-type:          Simple+extra-source-files:  ChangeLog.md+cabal-version:       >=1.10++source-repository head+  type:     git+  location: git://github.com/fgaz/polyvariadic.git++library+  exposed-modules:     Data.Accumulator, Data.Function.Polyvariadic+  -- other-modules:       +  other-extensions:    MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, GeneralizedNewtypeDeriving+  build-depends:       base >=4.7 && <4.10+                     , containers >=0.1 && <0.6+  if !impl(ghc >= 8.0)+    build-depends: semigroups == 0.18.*+  -- hs-source-dirs:      +  default-language:    Haskell2010+  ghc-options:         -Wall+