separated (empty) → 0.0.1
raw patch · 5 files changed
+308/−0 lines, 5 filesdep +QuickCheckdep +basedep +directorybuild-type:Customsetup-changed
Dependencies added: QuickCheck, base, directory, doctest, filepath, lens, semigroups
Files
- Setup.lhs +44/−0
- etc/LICENCE +27/−0
- separated.cabal +67/−0
- src/Data/Separated.hs +138/−0
- test/doctests.hs +32/−0
+ Setup.lhs view
@@ -0,0 +1,44 @@+#!/usr/bin/env runhaskell+\begin{code}+{-# OPTIONS_GHC -Wall #-}+module Main (main) where++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 = 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}
+ etc/LICENCE view
@@ -0,0 +1,27 @@+Copyright 2013 Tony Morris++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:+1. Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.+2. 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.+3. Neither the name of the author nor the names of his contributors+ may be used to endorse or promote products derived from this software+ without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 AUTHORS 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.
+ separated.cabal view
@@ -0,0 +1,67 @@+name: separated+version: 0.0.1+license: BSD3+license-File: etc/LICENCE+author: Tony Morris <ʇǝu˙sıɹɹoɯʇ@ןןǝʞsɐɥ>+maintainer: Tony Morris+copyright: Copyright (C) 2013 Tony Morris+synopsis: A data type with elements separated by values+category: Data+description: A data type with elements separated by values+homepage: https://github.com/tonymorris/separated+bug-reports: https://github.com/tonymorris/route/separated+cabal-version: >= 1.10+build-type: Custom++source-repository head+ type: git+ location: git@github.com:tonymorris/separated.git++flag small_base+ description: Choose the new, split-up base package.++library+ default-language:+ Haskell2010++ build-depends:+ base < 5 && >= 3+ , lens >= 3.10+ , semigroups >= 0.9++ ghc-options:+ -Wall++ default-extensions:+ NoImplicitPrelude++ hs-source-dirs:+ src++ exposed-modules:+ Data.Separated++test-suite doctests+ type:+ exitcode-stdio-1.0++ main-is:+ doctests.hs++ default-language:+ Haskell2010++ build-depends:+ base < 5 && >= 3,+ doctest >= 0.9.7,+ filepath >= 1.3,+ directory >= 1.1,+ QuickCheck >= 2.0++ ghc-options:+ -Wall+ -threaded++ hs-source-dirs:+ test+
+ src/Data/Separated.hs view
@@ -0,0 +1,138 @@+module Data.Separated(+ Separated(..)+, (~>)+, single+, separatedValues1+, separatedValues+, separatedHead+, separatedTail+, separators+) where++import Prelude(Eq, Ord, Show(..), Functor(..), Monad(..), fst, snd, zipWith, (.))+import Data.List.NonEmpty(NonEmpty(..), toList)+import Control.Lens(Lens', lens)+import Data.Semigroup(Semigroup(..))++-- $setup+-- >>> import Prelude(Eq(..), Num(..), String, Int, id)+-- >>> import Control.Lens(set, (^.))+-- >>> import Test.QuickCheck(Arbitrary(..))+-- >>> instance (Arbitrary a, Arbitrary s) => Arbitrary (Separated s a) where arbitrary = do a <- arbitrary; x <- arbitrary; return (Separated a x)++data Separated s a =+ Separated a [(s, a)]+ deriving (Eq, Ord)++instance (Show s, Show a) => Show (Separated s a) where+ show (Separated a x) =+ '[' : show a <> (x >>= \(s, y) -> show s <> show y) <> "]"++-- | Map across a @Separated@ on the element values.+--+-- prop> fmap id (x :: Separated Int String) == x+--+-- >>> fmap (+1) (single 1)+-- [2]+--+-- >>> fmap (+1) (set separatedTail [('a', 2), ('b', 3)] (single 1))+-- [2'a'3'b'4]+instance Functor (Separated s) where+ fmap f (Separated a x) =+ Separated (f a) (fmap (\(s, y) -> (s, f y)) x)++-- | Prepend a separator and element to the current tail.+--+-- >>> ('b', 9) ~> ('a', 8) ~> single 7+-- [7'b'9'a'8]+(~>) ::+ (s, a)+ -> Separated s a+ -> Separated s a+e ~> Separated a x =+ Separated a (e:x)++infixr 5 ~>++-- |+--+-- >>> single 4+-- [4]+--+-- prop> single x ^. separatedTail == []+single ::+ a+ -> Separated s a+single a =+ Separated a []++-- | Return all element values.+--+-- >>> separatedValues1 (single 8)+-- 8 :| []+--+-- >>> separatedValues1 (('a', 9) ~> single 8)+-- 8 :| [9]+--+-- prop> let h :| _ = separatedValues1 (single x) in h == (x :: Int)+--+-- prop> let _ :| t = separatedValues1 (e ~> single x) in t == fmap fst [e]+separatedValues1 ::+ Separated s a+ -> NonEmpty a+separatedValues1 (Separated a x) =+ a :| fmap snd x++-- | Return all element values.+--+-- >>> separatedValues (single 8)+-- [8]+--+-- >>> separatedValues (('a', 9) ~> single 8)+-- [8,9]+--+-- prop> let h : _ = separatedValues (single x) in h == (x :: Int)+--+-- prop> let _ : t = separatedValues (e ~> single x) in t == fmap fst [e]+separatedValues ::+ Separated s a+ -> [a]+separatedValues =+ toList . separatedValues1++-- | A lens on the first element value.+--+-- >>> single 7 ^. separatedHead+-- 7+--+-- prop> single x ^. separatedHead == (x :: Int)+separatedHead ::+ Lens' (Separated s a) a+separatedHead =+ lens (\(Separated a _) -> a) (\(Separated _ x) a -> Separated a x)++-- | A lens on the tail.+--+-- >>> single 7 ^. separatedHead+-- 7+--+-- prop> (e ~> single x) ^. separatedTail == [e]+separatedTail ::+ Lens' (Separated s a) [(s, a)]+separatedTail =+ lens (\(Separated _ x) -> x) (\(Separated a _) x -> Separated a x)++-- | Return all separator values.+--+-- >>> separators (('a', 8) ~> single 7)+-- "a"+--+-- >>> separators (('b', 9) ~> ('a', 8) ~> single 7)+-- "ba"+--+-- prop> separators (single x) == []+separators ::+ Separated s a+ -> [s]+separators (Separated _ x) =+ fmap fst x
+ test/doctests.hs view
@@ -0,0 +1,32 @@+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