packages feed

barecheck (empty) → 0.2.0.0

raw patch · 29 files changed

+676/−0 lines, 29 filesdep +QuickCheckdep +basedep +containerssetup-changed

Dependencies added: QuickCheck, base, containers, text, time

Files

+ LICENSE view
@@ -0,0 +1,31 @@+Copyright (c) 2014 Omari Norman.+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 Omari Norman nor the names of contributors+    to this software 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+HOLDER 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,4 @@+import Distribution.Simple++main :: IO ()+main = defaultMain
+ barecheck.cabal view
@@ -0,0 +1,85 @@+-- This Cabal file generated using the Cartel library.+-- Cartel is available at:+-- http://www.github.com/massysett/cartel+--+-- Script name used to generate: genCabal.hs+-- Generated on: 2014-08-04 09:08:04.876727 EDT+-- Cartel library version: 0.10.0.2+name: barecheck+version: 0.2.0.0+cabal-version: >= 1.14+build-type: Simple+license: BSD3+license-file: LICENSE+copyright: Copyright 2014 Omari Norman+author: Omari Norman, omari@smileystation.com+maintainer: Omari Norman, omari@smileystation.com+stability: Experimental+homepage: http://github.com/massysett/barecheck+bug-reports: http://github.com/massysett/barecheck/issues+synopsis: QuickCheck implementations for common types+description:+  Provides QuickCheck implementations for common types distributed+  with GHC and in the Haskell Platform.  The implementations+  are NOT provided through the QuickCheck Arbitrary and+  CoArbitrary typeclasses; instead, they are provided through+  ordinary, non-overloaded functions.  This avoids problems+  with orphan instances.+  .+  Implementations are provided through child modules of the+  module that provides the original type.  For example, for+  "Data.Map", look under "Data.Map.Generators",+  "Data.Map.Shrinkers", and "Data.Map.Coarbitrary".+  For instance, a function that generates a Map is at+  'Data.Map.Generators.map', while a function providing+  a coarbitrary implementation is at 'Data.Map.Coarbitrary.map'.+  Obviously this can lead to name conflicts, both between+  modules provided in this package and with other standard+  modules, so keep this in mind when you do your imports.+category: Testing+tested-with: GHC == 7.4.1, GHC == 7.6.3, GHC == 7.8.3+extra-source-files:+    minimum-versions.txt+  , current-versions.txt+  , genCabal.hs+  , sunlight-test.hs++source-repository head+  type: git+  location: http://github.com/massysett/barecheck.git++Library+  exposed-modules:+      Barecheck.Util+    , Data.Map.Coarbitrary+    , Data.Map.Generators+    , Data.Map.Shrinkers+    , Data.Monoid.Coarbitrary+    , Data.Monoid.Generators+    , Data.Monoid.Shrinkers+    , Data.Sequence.Coarbitrary+    , Data.Sequence.Generators+    , Data.Sequence.Shrinkers+    , Data.Text.Coarbitrary+    , Data.Text.Generators+    , Data.Text.Shrinkers+    , Data.Time.Coarbitrary+    , Data.Time.Generators+    , Data.Time.Shrinkers+    , Data.Tree.Coarbitrary+    , Data.Tree.Generators+    , Data.Tree.Shrinkers+    , Prelude.Coarbitrary+    , Prelude.Generators+    , Prelude.Shrinkers+  build-depends:+      QuickCheck ((> 2.7 || == 2.7) && < 2.8)+    , base ((> 4.5.0.0 || == 4.5.0.0) && < 4.8.0.0)+    , text ((> 0.11.0.0 || == 0.11.0.0) && < 1.2)+    , containers ((> 0.4.2.1 || == 0.4.2.1) && < 0.6)+    , time ((> 1.4 || == 1.4) && < 1.5)+  hs-source-dirs:+      lib+  ghc-options:+      -Wall+  default-language: Haskell2010
+ current-versions.txt view
+ genCabal.hs view
@@ -0,0 +1,115 @@+-- Generates the Cabal file using Cartel.+-- Written for Cartel version 0.10.0.2+-- Cartel is available at+-- http://github.com/massysett/cartel++module Main where++import qualified Cartel as A++versionInts :: [Int]+versionInts = [0,2,0,0]++version :: A.Version+version = A.Version versionInts++properties :: A.Properties+properties = A.empty+  { A.prName = "barecheck"+  , A.prVersion = version+  , A.prCabalVersion = (1,14)+  , A.prBuildType = A.Simple+  , A.prLicense = A.BSD3+  , A.prLicenseFile = "LICENSE"+  , A.prCopyright = "Copyright 2014 Omari Norman"+  , A.prAuthor = "Omari Norman, omari@smileystation.com"+  , A.prMaintainer = "Omari Norman, omari@smileystation.com"+  , A.prStability = "Experimental"+  , A.prHomepage = "http://github.com/massysett/barecheck"+  , A.prBugReports = "http://github.com/massysett/barecheck/issues"+  , A.prSynopsis = "QuickCheck implementations for common types"+  , A.prDescription =+    [ "Provides QuickCheck implementations for common types distributed"+    , "with GHC and in the Haskell Platform.  The implementations"+    , "are NOT provided through the QuickCheck Arbitrary and"+    , "CoArbitrary typeclasses; instead, they are provided through"+    , "ordinary, non-overloaded functions.  This avoids problems"+    , "with orphan instances."+    , ""+    , "Implementations are provided through child modules of the"+    , "module that provides the original type.  For example, for"+    , "\"Data.Map\", look under \"Data.Map.Generators\","+    , "\"Data.Map.Shrinkers\", and \"Data.Map.Coarbitrary\"."+    , "For instance, a function that generates a Map is at"+    , "\'Data.Map.Generators.map', while a function providing"+    , "a coarbitrary implementation is at \'Data.Map.Coarbitrary.map\'."+    , "Obviously this can lead to name conflicts, both between"+    , "modules provided in this package and with other standard"+    , "modules, so keep this in mind when you do your imports."+    ]+  , A.prCategory = "Testing"+  , A.prTestedWith =+    let ghc ints = (A.GHC, A.eq ints)+    in map ghc [[7,4,1], [7,6,3], [7,8,3]]+  , A.prExtraSourceFiles =+    [ "minimum-versions.txt"+    , "current-versions.txt"+    , "genCabal.hs"+    , "sunlight-test.hs"+    ]+  }++repo :: A.Repository+repo = A.empty+  { A.repoVcs = A.Git+  , A.repoKind = A.Head+  , A.repoLocation = "http://github.com/massysett/barecheck.git"+  }++quickcheck :: A.Package+quickcheck = A.nextBreaking "QuickCheck" [2,7]++base :: A.Package+base = A.closedOpen "base" [4,5,0,0] [4,8,0,0]++text :: A.Package+text = A.closedOpen "text" [0,11,0,0] [1,2]++containers :: A.Package+containers = A.closedOpen "containers" [0,4,2,1] [0,6]++time :: A.Package+time = A.closedOpen "time" [1,4] [1,5]++library+  :: [String]+  -- ^ Library modules+  -> A.Library+library ms = A.Library+  [ A.LibExposedModules ms+  , A.buildDepends+    [ quickcheck+    , base+    , text+    , containers+    , time+    ]+  , A.hsSourceDirs [ "lib" ]+  , A.ghcOptions [ "-Wall" ]+  , A.defaultLanguage A.Haskell2010+  ]++cabal+  :: [String]+  -- ^ Library modules+  -> A.Cabal+cabal ms = A.empty+  { A.cProperties = properties+  , A.cRepositories = [repo]+  , A.cLibrary = Just $ library ms+  }++main :: IO ()+main = do+  ms <- A.modules "lib"+  A.render "genCabal.hs" $ cabal ms
+ lib/Barecheck/Util.hs view
@@ -0,0 +1,8 @@+module Barecheck.Util where++import Test.QuickCheck++-- | 'variant' monomorphised to 'Int'; eliminates type defaulting+-- compiler warnings.+varInt :: Int -> Gen b -> Gen b+varInt = variant
+ lib/Data/Map/Coarbitrary.hs view
@@ -0,0 +1,17 @@+module Data.Map.Coarbitrary where++import Prelude hiding (map)+import qualified Data.Map as M+import Test.QuickCheck++map+  :: Ord k+  => ((k, a) -> Gen r -> Gen r)+  -> M.Map k a+  -> Gen r+  -> Gen r+map f m = go $ M.toList m+  where+    go ls = case ls of+      [] -> variant (0 :: Int)+      x:xs -> variant (1 :: Int) . f x . go xs
+ lib/Data/Map/Generators.hs view
@@ -0,0 +1,8 @@+module Data.Map.Generators where++import Prelude hiding (map)+import Test.QuickCheck+import qualified Data.Map as M++map :: Ord k => Gen [(k, a)] -> Gen (M.Map k a)+map = fmap M.fromList
+ lib/Data/Map/Shrinkers.hs view
@@ -0,0 +1,8 @@+module Data.Map.Shrinkers where++import Prelude hiding (map)+import Test.QuickCheck+import qualified Data.Map as M++map :: Ord k => ((k, a) -> [(k, a)]) -> M.Map k a -> [M.Map k a]+map s = fmap M.fromList . shrinkList s . M.toList
+ lib/Data/Monoid/Coarbitrary.hs view
@@ -0,0 +1,14 @@+module Data.Monoid.Coarbitrary where++import Test.QuickCheck+import qualified Data.Monoid as O++last :: (a -> Gen b -> Gen b) -> O.Last a -> Gen b -> Gen b+last f (O.Last m) = case m of+  Nothing -> variant (0 :: Int)+  Just a -> variant (1 :: Int) . f a++first :: (a -> Gen b -> Gen b) -> O.First a -> Gen b -> Gen b+first f (O.First m) = case m of+  Nothing -> variant (0 :: Int)+  Just a -> variant (1 :: Int) . f a
+ lib/Data/Monoid/Generators.hs view
@@ -0,0 +1,12 @@+module Data.Monoid.Generators where++import qualified Data.Monoid as O+import Test.QuickCheck++last :: Gen a -> Gen (O.Last a)+last g = fmap O.Last $ frequency+  [ (3, fmap Just g), (1, return Nothing) ]++first :: Gen a -> Gen (O.First a)+first g = fmap O.First $ frequency+  [ (3, fmap Just g), (1, return Nothing) ]
+ lib/Data/Monoid/Shrinkers.hs view
@@ -0,0 +1,13 @@+module Data.Monoid.Shrinkers where++import qualified Data.Monoid as O++last :: (a -> [a]) -> O.Last a -> [O.Last a]+last f (O.Last l) = case l of+  Nothing -> []+  Just a -> map O.Last $ Nothing : [Just x | x <- f a]++first :: (a -> [a]) -> O.First a -> [O.First a]+first f (O.First l) = case l of+  Nothing -> []+  Just a -> map O.First $ Nothing : [Just x | x <- f a]
+ lib/Data/Sequence/Coarbitrary.hs view
@@ -0,0 +1,10 @@+module Data.Sequence.Coarbitrary where++import Data.Sequence+import Test.QuickCheck+import Prelude hiding (seq)++seq :: (a -> Gen b -> Gen b) -> Seq a -> Gen b -> Gen b+seq f s = case viewl s of+  EmptyL -> variant (0 :: Int)+  a :< rest -> variant (1 :: Int) . f a . seq f rest
+ lib/Data/Sequence/Generators.hs view
@@ -0,0 +1,8 @@+module Data.Sequence.Generators where++import Data.Sequence+import Test.QuickCheck+import Prelude hiding (seq)++seq :: Gen a -> Gen (Seq a)+seq = fmap fromList . listOf
+ lib/Data/Sequence/Shrinkers.hs view
@@ -0,0 +1,9 @@+module Data.Sequence.Shrinkers where++import Test.QuickCheck+import Data.Sequence+import Prelude hiding (seq)+import Data.Foldable++seq :: (a -> [a]) -> Seq a -> [Seq a]+seq f = map fromList . shrinkList f . toList
+ lib/Data/Text/Coarbitrary.hs view
@@ -0,0 +1,10 @@+module Data.Text.Coarbitrary where++import Test.QuickCheck+import Data.Text (Text)+import qualified Data.Text as X++text :: Text -> Gen b -> Gen b+text t = case X.uncons t of+  Nothing -> variant (0 :: Int)+  Just (x, xs) -> variant (1 :: Int) . coarbitrary x . text xs
+ lib/Data/Text/Generators.hs view
@@ -0,0 +1,9 @@+module Data.Text.Generators where++import Test.QuickCheck+import qualified Data.Text as X+import Data.Text (Text)++text :: Gen Char -> Gen Text+text = fmap X.pack . listOf+
+ lib/Data/Text/Shrinkers.hs view
@@ -0,0 +1,8 @@+module Data.Text.Shrinkers where++import Data.Text (Text)+import qualified Data.Text as X+import Test.QuickCheck++text :: (Char -> [Char]) -> Text -> [Text]+text f = map X.pack . shrinkList f . X.unpack
+ lib/Data/Time/Coarbitrary.hs view
@@ -0,0 +1,13 @@+module Data.Time.Coarbitrary where++import Data.Time+import Test.QuickCheck++day :: Day -> Gen b -> Gen b+day (ModifiedJulianDay i) = variant i++diffTime :: DiffTime -> Gen b -> Gen b+diffTime d = coarbitrary (toRational d)++uTCTime :: UTCTime -> Gen b -> Gen b+uTCTime (UTCTime d t) = day d . diffTime t
+ lib/Data/Time/Generators.hs view
@@ -0,0 +1,14 @@+module Data.Time.Generators where++import Test.QuickCheck+import Data.Time+import Control.Monad++day :: Gen Day+day = fmap ModifiedJulianDay arbitrarySizedIntegral++diffTime :: Gen DiffTime+diffTime = fmap (picosecondsToDiffTime . abs) arbitrary++uTCTime :: Gen UTCTime+uTCTime = liftM2 UTCTime day diffTime
+ lib/Data/Time/Shrinkers.hs view
@@ -0,0 +1,15 @@+module Data.Time.Shrinkers where++import Data.Time+import Test.QuickCheck+import Prelude.Shrinkers++day :: Day -> [Day]+day = fmap ModifiedJulianDay . shrinkIntegral . toModifiedJulianDay++diffTime :: DiffTime -> [DiffTime]+diffTime _ = []++uTCTime :: UTCTime -> [UTCTime]+uTCTime (UTCTime a t) =+  [ UTCTime a' t' | (a', t') <- tuple2 day diffTime (a, t) ]
+ lib/Data/Tree/Coarbitrary.hs view
@@ -0,0 +1,12 @@+module Data.Tree.Coarbitrary where++import Data.Tree+import Test.QuickCheck+import Prelude.Coarbitrary++tree+  :: (a -> Gen b -> Gen b)+  -> Tree a+  -> Gen b+  -> Gen b+tree f (Node a as) = f a . list (tree f) as
+ lib/Data/Tree/Generators.hs view
@@ -0,0 +1,20 @@+module Data.Tree.Generators where++import Data.Tree+import Test.QuickCheck+import Control.Monad++tree+  :: (Int -> Int)+  -- ^ This function is applied to the size parameter.  It determines+  -- the length of the list in child forests, to prevent this function+  -- from generating trees that are infinitely large.  Here, supply a+  -- function that reduces the size parameter by some amount; using+  -- @(\`div\` 2)@ is typical, though if you want to restrict the size+  -- of trees produced even more you might try something like+  -- @(\`div\` 5)@.+  -> Gen a+  -- ^ Generates a root label.+  -> Gen (Tree a)+tree f g = liftM2 Node g (sized $ \s -> resize (f s) (listOf (tree f g)))+
+ lib/Data/Tree/Shrinkers.hs view
@@ -0,0 +1,12 @@+module Data.Tree.Shrinkers where++import Data.Tree+import Prelude.Shrinkers+import Test.QuickCheck++tree+  :: (a -> [a])+  -> Tree a+  -> [Tree a]+tree f (Node a as) = as +++  [ Node n cs | (n, cs) <- tuple2 f (shrinkList (tree f)) (a, as) ]
+ lib/Prelude/Coarbitrary.hs view
@@ -0,0 +1,68 @@+module Prelude.Coarbitrary where++import Test.QuickCheck+import Prelude hiding (maybe, either)+import Barecheck.Util++maybe :: (a -> Gen b -> Gen b) -> Maybe a -> Gen b -> Gen b+maybe f m = case m of+  Nothing -> varInt 0+  Just x -> varInt 1 . f x++either+  :: (a -> Gen c -> Gen c)+  -> (b -> Gen c -> Gen c)+  -> Either a b+  -> Gen c+  -> Gen c+either fa fb ei = case ei of+  Left a -> varInt 0 . fa a+  Right b -> varInt 1 . fb b++list+  :: (a -> Gen b -> Gen b)+  -> [a]+  -> Gen b+  -> Gen b+list f xs = case xs of+  [] -> varInt 0+  a:as -> varInt 1 . f a . list f as++tuple2+  :: (a -> Gen r -> Gen r)+  -> (b -> Gen r -> Gen r)+  -> (a, b)+  -> Gen r+  -> Gen r+tuple2 fa fb (a, b) = fa a . fb b++tuple3+  :: (a -> Gen r -> Gen r)+  -> (b -> Gen r -> Gen r)+  -> (c -> Gen r -> Gen r)+  -> (a, b, c)+  -> Gen r+  -> Gen r+tuple3 fa fb fc (a, b, c) = fa a . fb b . fc c++tuple4+  :: (a -> Gen r -> Gen r)+  -> (b -> Gen r -> Gen r)+  -> (c -> Gen r -> Gen r)+  -> (d -> Gen r -> Gen r)+  -> (a, b, c, d)+  -> Gen r+  -> Gen r+tuple4 fa fb fc fd (a, b, c, d) = fa a . fb b . fc c . fd d++tuple5+  :: (a -> Gen r -> Gen r)+  -> (b -> Gen r -> Gen r)+  -> (c -> Gen r -> Gen r)+  -> (d -> Gen r -> Gen r)+  -> (e -> Gen r -> Gen r)+  -> (a, b, c, d, e)+  -> Gen r+  -> Gen r+tuple5 fa fb fc fd fe (a, b, c, d, e) = fa a . fb b . fc c . fd d . fe e+
+ lib/Prelude/Generators.hs view
@@ -0,0 +1,99 @@+-- | Generators for "Prelude" types.+--+-- This module also contains function generators, like 'function1' and+-- 'function2'.  These generate random functions.  To use these, get a+-- coarbitrary function from one of the modules whose name ends in+-- @Coarbitrary@ or by using the QuickCheck 'coarbitrary' function,+-- along with using a generator for the function's result type.  For+-- example:+--+-- @+--    module MyModule where+--+--    import Test.QuickCheck+--    import qualified Prelude.Generators as G+--    import qualified Data.Text.Coarbitrary as C+--    import qualified Data.Text.Generators as G+--+--    genTextToMaybeText :: Gen (Text -> Maybe Text)+--    genTextToMaybeText = function1 C.text (G.maybe (G.text arbitrary))+-- @+++module Prelude.Generators where++import Test.QuickCheck+import Prelude hiding (maybe, either)+import Test.QuickCheck.Gen.Unsafe+import Control.Monad++maybe :: Gen a -> Gen (Maybe a)+maybe g = frequency [(3, fmap Just g), (1, return Nothing)]++either :: Gen a -> Gen b -> Gen (Either a b)+either a b = oneof [ fmap Left a, fmap Right b ]++function1+  :: (a -> Gen b -> Gen b)+  -> Gen b+  -> Gen (a -> b)+function1 perturb gen = promote (`perturb` gen)++function2+  :: (a -> Gen r -> Gen r)+  -> (b -> Gen r -> Gen r)+  -> Gen r+  -> Gen (a -> b -> r)+function2 p1 p2 = fmap f . function1 p'+  where+    p' (a, b) = p1 a . p2 b+    f g = \a b -> g (a, b)++function3+  :: (a -> Gen r -> Gen r)+  -> (b -> Gen r -> Gen r)+  -> (c -> Gen r -> Gen r)+  -> Gen r+  -> Gen (a -> b -> c -> r)+function3 p1 p2 p3 = fmap f . function1 p'+  where+    p' (a, b, c) = p1 a . p2 b . p3 c+    f g = \a b c -> g (a, b, c)++function4+  :: (a -> Gen r -> Gen r)+  -> (b -> Gen r -> Gen r)+  -> (c -> Gen r -> Gen r)+  -> (d -> Gen r -> Gen r)+  -> Gen r+  -> Gen (a -> b -> c -> d -> r)+function4 p1 p2 p3 p4 = fmap f . function1 p'+  where+    p' (a, b, c, d) = p1 a . p2 b . p3 c . p4 d+    f g = \a b c d -> g (a, b, c, d)++function5+  :: (a -> Gen r -> Gen r)+  -> (b -> Gen r -> Gen r)+  -> (c -> Gen r -> Gen r)+  -> (d -> Gen r -> Gen r)+  -> (e -> Gen r -> Gen r)+  -> Gen r+  -> Gen (a -> b -> c -> d -> e -> r)+function5 p1 p2 p3 p4 p5 = fmap f . function1 p'+  where+    p' (a, b, c, d, e) = p1 a . p2 b . p3 c . p4 d . p5 e+    f g = \a b c d e -> g (a, b, c, d, e)+++tuple2 :: Gen a -> Gen b -> Gen (a, b)+tuple2 a b = liftM2 (,) a b++tuple3 :: Gen a -> Gen b -> Gen c -> Gen (a, b, c)+tuple3 a b c = liftM3 (,,) a b c++tuple4 :: Gen a -> Gen b -> Gen c -> Gen d -> Gen (a, b, c, d)+tuple4 a b c d = liftM4 (,,,) a b c d++tuple5 :: Gen a -> Gen b -> Gen c -> Gen d -> Gen e -> Gen (a, b, c, d, e)+tuple5 a b c d e = liftM5 (,,,,) a b c d e
+ lib/Prelude/Shrinkers.hs view
@@ -0,0 +1,54 @@+module Prelude.Shrinkers where++import Prelude hiding (maybe, either)++maybe :: (a -> [a]) -> Maybe a -> [Maybe a]+maybe f m = case m of+  Nothing -> []+  Just x -> Nothing : map Just (f x)++either :: (a -> [a]) -> (b -> [b]) -> Either a b -> [Either a b]+either fa fb ei = case ei of+  Left a -> map Left (fa a)+  Right b -> map Right (fb b)++tuple2 :: (a -> [a]) -> (b -> [b]) -> (a, b) -> [(a, b)]+tuple2 fa fb (a, b) =+     [ (a', b) | a' <- fa a ]+  ++ [ (a, b') | b' <- fb b ]++tuple3+  :: (a -> [a])+  -> (b -> [b])+  -> (c -> [c])+  -> (a, b, c)+  -> [(a, b, c)]+tuple3 fa fb fc (a, b, c) =+  [ (a', b', c') | (a', (b', c'))+    <- tuple2 fa (tuple2 fb fc) (a, (b, c)) ]++tuple4+  :: (a -> [a])+  -> (b -> [b])+  -> (c -> [c])+  -> (d -> [d])+  -> (a, b, c, d)+  -> [(a, b, c, d)]+tuple4 fa fb fc fd (a, b, c, d) =+  [ (a', b', c', d') | (a', (b', (c', d')))+    <- tuple2 fa (tuple2 fb (tuple2 fc fd)) (a, (b, (c, d))) ]++tuple5+  :: (a -> [a])+  -> (b -> [b])+  -> (c -> [c])+  -> (d -> [d])+  -> (e -> [e])+  -> (a, b, c, d, e)+  -> [(a, b, c, d, e)]+tuple5 fa fb fc fd fe (a, b, c, d, e) =+  [ (a', b', c', d', e') | (a', (b', (c', (d', e'))))+    <- tuple2 fa (tuple2 fb (tuple2 fc (tuple2 fd fe)))+                  (a, (b, (c, (d, e)))) ]++
+ minimum-versions.txt view
+ sunlight-test.hs view