distributive 0.2.2 → 0.3
raw patch · 12 files changed
+341/−100 lines, 12 filesdep +directorydep +doctestdep +filepathdep ~basebuild-type:Customsetup-changedPVP ok
version bump matches the API change (PVP)
Dependencies added: directory, doctest, filepath, transformers-compat
Dependency ranges changed: base
API changes (from Hackage documentation)
+ Data.Distributive: instance Distributive f => Distributive (Backwards f)
+ Data.Distributive: instance Distributive f => Distributive (Reverse f)
Files
- .ghci +1/−0
- .travis.yml +25/−0
- .vim.custom +31/−0
- CHANGELOG.markdown +4/−0
- Data/Distributive.hs +0/−87
- README.markdown +32/−0
- Setup.lhs +41/−4
- config +16/−0
- distributive.cabal +40/−9
- src/Data/Distributive.hs +105/−0
- tests/doctests.hs +30/−0
- travis-cabal-apt-install +16/−0
+ .ghci view
@@ -0,0 +1,1 @@+:set -isrc -idist/build/autogen -optP-include -optPdist/build/autogen/cabal_macros.h
+ .travis.yml view
@@ -0,0 +1,25 @@+language: haskell+before_install:+ # Uncomment whenever hackage is down.+ # - mkdir -p ~/.cabal && cp config ~/.cabal/config && cabal update++ # Try installing some of the build-deps with apt-get for speed.+ - ./travis-cabal-apt-install --only-dependencies --force-reinstall $mode++install:+ - cabal configure -flib-Werror $mode+ - cabal build++script:+ - $script++notifications:+ irc:+ channels:+ - "irc.freenode.org#haskell-lens"+ skip_join: true+ template:+ - "\x0313distributive\x03/\x0306%{branch}\x03 \x0314%{commit}\x03 %{build_url} %{message}"++env:+ - mode="--enable-tests" script="cabal test"
+ .vim.custom view
@@ -0,0 +1,31 @@+" Add the following to your .vimrc to automatically load this on startup++" if filereadable(".vim.custom")+" so .vim.custom+" endif++function StripTrailingWhitespace()+ let myline=line(".")+ let mycolumn = col(".")+ silent %s/ *$//+ call cursor(myline, mycolumn)+endfunction++" enable syntax highlighting+syntax on++" search for the tags file anywhere between here and /+set tags=TAGS;/++" highlight tabs and trailing spaces+set listchars=tab:‗‗,trail:‗+set list++" f2 runs hasktags+map <F2> :exec ":!hasktags -x -c --ignore src"<CR><CR>++" strip trailing whitespace before saving+" au BufWritePre *.hs,*.markdown silent! cal StripTrailingWhitespace()++" rebuild hasktags after saving+au BufWritePost *.hs silent! :exec ":!hasktags -x -c --ignore src"
+ CHANGELOG.markdown view
@@ -0,0 +1,4 @@+0.3+---+* Added instances for `Control.Applicative.Backwards` and `Data.Functor.Reverse` from `transformers` 0.3, taking them from `transformers-compat` if necessary for `transformers` 0.2+
− Data/Distributive.hs
@@ -1,87 +0,0 @@--------------------------------------------------------------------------------- |--- Module : Data.Distributive--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : provisional--- Portability : portable---------------------------------------------------------------------------------module Data.Distributive - ( Distributive(..)- , cotraverse- , comapM- ) where--import Control.Applicative-import Control.Monad (liftM)-import Control.Monad.Trans.Identity-import Control.Monad.Trans.Reader-import Control.Monad.Instances ()-import Data.Functor.Identity-import Data.Functor.Product-import Data.Functor.Compose---- | This is the categorical dual of 'Traversable'. However, there appears--- to be little benefit to allow the distribution via an arbitrary comonad--- so we restrict ourselves to 'Functor'.--- --- Minimal complete definition: 'distribute' or 'collect'------ To be distributable a container will need to have a way to consistently--- zip a potentially infinite number of copies of itself. This effectively--- means that the holes in all values of that type, must have the same --- cardinality, fixed sized vectors, infinite streams, functions, etc.--- and no extra information to try to merge together.--class Functor g => Distributive g where- -- | The dual of 'Data.Traversable.sequence'- -- - -- > distribute = collect id- distribute :: Functor f => f (g a) -> g (f a)- distribute = collect id-- -- | - -- > collect = distribute . fmap f- collect :: Functor f => (a -> g b) -> f a -> g (f b)- collect f = distribute . fmap f-- -- | - -- > distributeM = fmap unwrapMonad . distribute . WrapMonad- distributeM :: Monad m => m (g a) -> g (m a)- distributeM = fmap unwrapMonad . distribute . WrapMonad -- -- | - -- > collectM = distributeM . liftM f- collectM :: Monad m => (a -> g b) -> m a -> g (m b)- collectM f = distributeM . liftM f--cotraverse :: (Functor f, Distributive g) => (f a -> b) -> f (g a) -> g b-cotraverse f = fmap f . distribute--comapM :: (Monad m, Distributive g) => (m a -> b) -> m (g a) -> g b-comapM f = fmap f . distributeM--instance Distributive Identity where- collect f = Identity . fmap (runIdentity . f)- distribute = Identity . fmap runIdentity--instance Distributive ((->)e) where- distribute a e = fmap ($e) a--instance Distributive g => Distributive (ReaderT e g) where- distribute a = ReaderT $ \e -> collect (flip runReaderT e) a--instance Distributive g => Distributive (IdentityT g) where- collect f = IdentityT . collect (runIdentityT . f)--instance (Distributive f, Distributive g) => Distributive (Compose f g) where- distribute = Compose . fmap distribute . collect getCompose--instance (Distributive f, Distributive g) => Distributive (Product f g) where- -- distribute :: Functor w => w (Product f g a) -> Product f g (w a)- distribute wp = Pair (collect fstP wp) (collect sndP wp) where - fstP (Pair a _) = a- sndP (Pair _ b) = b
+ README.markdown view
@@ -0,0 +1,32 @@+distributive+============++[](http://travis-ci.org/ekmett/distributive)++This package provides the notion that is categorically dual to `Traversable`.++A `Distributive` `Functor` is one that you can push any functor inside of.++```haskell+distribute :: (Functor f, Distributive g) => f (g a) -> g (f a)+```++Compare this with the corresponding Traversable notion, `sequenceA`.++```haskell+sequenceA :: (Applicative f, Traversable g) => g (f a) -> f (g a)+```++This package includes instances for common types, and includes other methods similar to `traverse` which fuse the use of `fmap`.++We only require `Functor` rather than some dual notion to `Applicative`, because the latter cannot meaningfully exist in Haskell+since all comonoids there are trivial.++Contact Information+-------------------++Contributions and bug reports are welcome!++Please feel free to contact me through github or on the #haskell IRC channel on irc.freenode.net.++-Edward Kmett
Setup.lhs view
@@ -1,7 +1,44 @@ #!/usr/bin/runhaskell-> module Main (main) where+\begin{code}+{-# OPTIONS_GHC -Wall #-}+module Main (main) where -> import Distribution.Simple+import Data.List ( nub )+import Data.Version ( showVersion )+import Distribution.Package ( PackageName(PackageName), PackageId, InstalledPackageId, packageVersion, packageName )+import Distribution.PackageDescription ( PackageDescription(), TestSuite(..) )+import Distribution.Simple ( defaultMainWithHooks, UserHooks(..), simpleUserHooks )+import Distribution.Simple.Utils ( rewriteFile, createDirectoryIfMissingVerbose )+import Distribution.Simple.BuildPaths ( autogenModulesDir )+import Distribution.Simple.Setup ( BuildFlags(buildVerbosity), fromFlag )+import Distribution.Simple.LocalBuildInfo ( withLibLBI, withTestLBI, LocalBuildInfo(), ComponentLocalBuildInfo(componentPackageDeps) )+import Distribution.Verbosity ( Verbosity )+import System.FilePath ( (</>) ) -> main :: IO ()-> main = defaultMain+main :: IO ()+main = defaultMainWithHooks simpleUserHooks+ { buildHook = \pkg lbi hooks flags -> do+ generateBuildModule (fromFlag (buildVerbosity flags)) pkg lbi+ buildHook simpleUserHooks pkg lbi hooks flags+ }++generateBuildModule :: Verbosity -> PackageDescription -> LocalBuildInfo -> IO ()+generateBuildModule verbosity pkg lbi = do+ let dir = autogenModulesDir lbi+ createDirectoryIfMissingVerbose verbosity True dir+ withLibLBI pkg lbi $ \_ libcfg -> do+ withTestLBI pkg lbi $ \suite suitecfg -> do+ rewriteFile (dir </> "Build_" ++ testName suite ++ ".hs") $ unlines+ [ "module Build_" ++ testName suite ++ " where"+ , "deps :: [String]"+ , "deps = " ++ (show $ formatdeps (testDeps libcfg suitecfg))+ ]+ where+ formatdeps = map (formatone . snd)+ formatone p = case packageName p of+ PackageName n -> n ++ "-" ++ showVersion (packageVersion p)++testDeps :: ComponentLocalBuildInfo -> ComponentLocalBuildInfo -> [(InstalledPackageId, PackageId)]+testDeps xs ys = nub $ componentPackageDeps xs ++ componentPackageDeps ys++\end{code}
+ config view
@@ -0,0 +1,16 @@+-- This provides a custom ~/.cabal/config file for use when hackage is down that should work on unix+--+-- This is particularly useful for travis-ci to get it to stop complaining+-- about a broken build when everything is still correct on our end.+--+-- This uses Luite Stegeman's mirror of hackage provided by his 'hdiff' site instead+--+-- To enable this, uncomment the before_script in .travis.yml++remote-repo: hdiff.luite.com:http://hdiff.luite.com/packages/archive+remote-repo-cache: ~/.cabal/packages+world-file: ~/.cabal/world+build-summary: ~/.cabal/logs/build.log+remote-build-reporting: anonymous+install-dirs user+install-dirs global
distributive.cabal view
@@ -1,28 +1,59 @@ name: distributive category: Data Structures-version: 0.2.2+version: 0.3 license: BSD3-cabal-version: >= 1.6+cabal-version: >= 1.8 license-file: LICENSE author: Edward A. Kmett maintainer: Edward A. Kmett <ekmett@gmail.com> stability: provisional homepage: http://github.com/ekmett/distributive/+bug-reports: http://github.com/ekmett/distributive/issues copyright: Copyright (C) 2011 Edward A. Kmett synopsis: Haskell 98 Distributive functors -- Dual to Traversable description: Haskell 98 Distributive functors -- Dual to Traversable-build-type: Simple+build-type: Custom+extra-source-files:+ .ghci+ .travis.yml+ .vim.custom+ config+ travis-cabal-apt-install+ CHANGELOG.markdown+ README.markdown source-repository head type: git location: git://github.com/ekmett/distributive.git +flag lib-Werror+ manual: True+ default: False+ library- build-depends: - base >= 4 && < 5,- transformers >= 0.2 && < 0.4+ build-depends:+ base >= 4 && < 5,+ transformers >= 0.2 && < 0.4,+ transformers-compat >= 0.1 && < 0.2 - exposed-modules:- Data.Distributive+ hs-source-dirs: src+ exposed-modules: Data.Distributive - ghc-options: -Wall+ if flag(lib-Werror)+ ghc-options: -Werror+ else+ ghc-options: -Wall++-- Verify the results of the examples+test-suite doctests+ type: exitcode-stdio-1.0+ main-is: doctests.hs+ build-depends:+ base >= 4,+ directory >= 1.0,+ doctest >= 0.9.1,+ filepath >= 1.2+ ghc-options: -Wall -threaded+ if impl(ghc<7.6.1)+ ghc-options: -Werror+ hs-source-dirs: tests
+ src/Data/Distributive.hs view
@@ -0,0 +1,105 @@+-----------------------------------------------------------------------------+-- |+-- Module : Data.Distributive+-- Copyright : (C) 2011-2012 Edward Kmett+-- License : BSD-style (see the file LICENSE)+--+-- Maintainer : Edward Kmett <ekmett@gmail.com>+-- Stability : provisional+-- Portability : portable+--+----------------------------------------------------------------------------+module Data.Distributive+ ( Distributive(..)+ , cotraverse+ , comapM+ ) where++import Control.Applicative+import Control.Applicative.Backwards+import Control.Monad (liftM)+import Control.Monad.Instances ()+import Control.Monad.Trans.Identity+import Control.Monad.Trans.Reader+import Data.Functor.Compose+import Data.Functor.Identity+import Data.Functor.Product+import Data.Functor.Reverse++{-# ANN module "ignore Use section" #-}++-- | This is the categorical dual of 'Traversable'. However, there appears+-- to be little benefit to allow the distribution via an arbitrary comonad+-- so we restrict ourselves to 'Functor'.+--+-- Minimal complete definition: 'distribute' or 'collect'+--+-- To be distributable a container will need to have a way to consistently+-- zip a potentially infinite number of copies of itself. This effectively+-- means that the holes in all values of that type, must have the same+-- cardinality, fixed sized vectors, infinite streams, functions, etc.+-- and no extra information to try to merge together.+class Functor g => Distributive g where+ -- | The dual of 'Data.Traversable.sequenceA'+ --+ -- >>> distribute [(+1),(+2)] 1+ -- [2,3]+ --+ -- @'distribute' = 'collect' 'id'@+ distribute :: Functor f => f (g a) -> g (f a)+ distribute = collect id++ -- |+ -- @'collect' = 'distribute' . 'fmap' f@+ collect :: Functor f => (a -> g b) -> f a -> g (f b)+ collect f = distribute . fmap f++ -- | The dual of 'Data.Traversable.sequence'+ --+ -- @'distributeM' = 'fmap' 'unwrapMonad' . 'distribute' . 'WrapMonad'@+ distributeM :: Monad m => m (g a) -> g (m a)+ distributeM = fmap unwrapMonad . distribute . WrapMonad++ -- |+ -- @'collectM' = 'distributeM' . 'liftM' f@+ collectM :: Monad m => (a -> g b) -> m a -> g (m b)+ collectM f = distributeM . liftM f++-- | The dual of 'Data.Traversable.traverse'+--+-- @'cotraverse' f = 'fmap' f . 'distribute'@+cotraverse :: (Functor f, Distributive g) => (f a -> b) -> f (g a) -> g b+cotraverse f = fmap f . distribute++-- | The dual of 'Data.Traversable.mapM'+--+-- @'comapM' f = 'fmap' f . 'distributeM'@+comapM :: (Monad m, Distributive g) => (m a -> b) -> m (g a) -> g b+comapM f = fmap f . distributeM++instance Distributive Identity where+ collect f = Identity . fmap (runIdentity . f)+ distribute = Identity . fmap runIdentity++instance Distributive ((->)e) where+ distribute a e = fmap ($e) a++instance Distributive g => Distributive (ReaderT e g) where+ distribute a = ReaderT $ \e -> collect (flip runReaderT e) a++instance Distributive g => Distributive (IdentityT g) where+ collect f = IdentityT . collect (runIdentityT . f)++instance (Distributive f, Distributive g) => Distributive (Compose f g) where+ distribute = Compose . fmap distribute . collect getCompose++instance (Distributive f, Distributive g) => Distributive (Product f g) where+ distribute wp = Pair (collect fstP wp) (collect sndP wp) where+ fstP (Pair a _) = a+ sndP (Pair _ b) = b++instance Distributive f => Distributive (Backwards f) where+ distribute = Backwards . collect forwards++instance Distributive f => Distributive (Reverse f) where+ distribute = Reverse . collect getReverse
+ tests/doctests.hs view
@@ -0,0 +1,30 @@+module Main where++import Build_doctests (deps)+import Control.Applicative+import Control.Monad+import Data.List+import System.Directory+import System.FilePath+import Test.DocTest++main :: IO ()+main = getSources >>= \sources -> doctest $+ "-isrc"+ : "-idist/build/autogen"+ : "-optP-include"+ : "-optPdist/build/autogen/cabal_macros.h"+ : "-hide-all-packages"+ : map ("-package="++) deps ++ sources++getSources :: IO [FilePath]+getSources = filter (isSuffixOf ".hs") <$> go "src"+ where+ go dir = do+ (dirs, files) <- getFilesAndDirectories dir+ (files ++) . concat <$> mapM go dirs++getFilesAndDirectories :: FilePath -> IO ([FilePath], [FilePath])+getFilesAndDirectories dir = do+ c <- map (dir </>) . filter (`notElem` ["..", "."]) <$> getDirectoryContents dir+ (,) <$> filterM doesDirectoryExist c <*> filterM doesFileExist c
+ travis-cabal-apt-install view
@@ -0,0 +1,16 @@+#!/bin/sh+set -eu++sudo apt-get -q update+sudo apt-get -q -y install dctrl-tools++# Try installing some of the build-deps with apt-get for speed.+eval "$(+ printf '%s' "grep-aptavail -n -sPackage '(' -FFALSE -X FALSE ')'"+ 2>/dev/null cabal install "$@" --dry-run -v | \+ sed -nre "s/^([^ ]+)-[0-9.]+ \(.*$/ -o '(' -FPackage -X libghc-\1-dev ')'/p" | \+ xargs -d'\n'+)" | sort -u | xargs -d'\n' sudo apt-get -q -y install -- libghc-quickcheck2-dev++# Install whatever is still needed with cabal.+cabal install "$@"