constraint-tuples 0.1 → 0.1.1
raw patch · 7 files changed
+277/−209 lines, 7 filesdep −base-compat-batteriesdep −optparse-applicativePVP ok
version bump matches the API change (PVP)
Dependencies removed: base-compat-batteries, optparse-applicative
API changes (from Hackage documentation)
Files
- CHANGELOG.md +5/−0
- constraint-tuples.cabal +7/−19
- exe/GeneratorScript.hs +0/−189
- generator-script/LICENSE +30/−0
- generator-script/exe/GeneratorScript.hs +194/−0
- generator-script/generator-script.cabal +40/−0
- src/Data/Tuple/Constraint.hs +1/−1
CHANGELOG.md view
@@ -1,2 +1,7 @@+### 0.1.1 [2019.10.21]+* Split `generator-script` out of the main `.cabal` file, as it is only used+ for development purposes.+* Minor Haddock fixes.+ ## 0.1 [2019.10.14] * First version.
constraint-tuples.cabal view
@@ -1,6 +1,6 @@ cabal-version: >=1.10 name: constraint-tuples-version: 0.1+version: 0.1.1 synopsis: Partially applicable constraint tuples description: This library provides classes that emulate the behavior of GHC's constraint tuple syntax. Unlike GHC's built-in@@ -27,7 +27,12 @@ copyright: (C) 2018-2019 Ryan Scott category: Data build-type: Simple-extra-source-files: CHANGELOG.md, README.md, GenCTuples.sh+extra-source-files: CHANGELOG.md+ README.md+ GenCTuples.sh+ generator-script/LICENSE+ generator-script/generator-script.cabal+ generator-script/exe/GeneratorScript.hs tested-with: GHC == 7.6.3 , GHC == 7.8.4 , GHC == 7.10.3@@ -41,11 +46,6 @@ type: git location: https://github.com/RyanGlScott/constraint-tuples -flag generator-script- description: Build the script which generates the source code for- this library.- default: False- library exposed-modules: Data.Tuple.Constraint Data.Tuple.Constraint.ClassNewtype@@ -53,15 +53,3 @@ hs-source-dirs: src default-language: Haskell2010 ghc-options: -Wall--executable generator-script- if !flag(generator-script)- buildable: False-- main-is: GeneratorScript.hs- build-depends: base >= 4.6 && < 5- , base-compat-batteries >= 0.10 && < 0.12- , optparse-applicative >= 0.13 && < 0.16- hs-source-dirs: exe- default-language: Haskell2010- ghc-options: -Wall -threaded -rtsopts
− exe/GeneratorScript.hs
@@ -1,189 +0,0 @@-{-# LANGUAGE NamedFieldPuns #-}--- | The script that generates the source code for "Data.Tuple.Constraint" and--- "Data.Tuple.Constraint.ClassNewtype". See the @GenCTuple.sh@ script for how--- to invoke this.-module Main (main) where--import Data.List.Compat-import Prelude ()-import Prelude.Compat-import Options.Applicative--data Args = Args- { output :: FilePath- , classNewtype :: Bool- } deriving Show--argsParser :: Parser Args-argsParser = Args- <$> strOption- ( long "output"- <> short 'o'- <> metavar "PATH"- <> help "The file to which to write the source code" )- <*> switch- ( long "class-newtype"- <> help "Generate the source code for Data.Tuple.Constraint.ClassNewtype" )--main :: IO ()-main = execParser opts >>= generate- where- opts = info (argsParser <**> helper)- ( fullDesc- <> progDesc spiel- <> header spiel )-- spiel = "Generate the source code for Data.Tuple.Constraint{,.ClassNewtype}"--generate :: Args -> IO ()-generate args@Args{output} =- let sourceCode = unlines $ preamble args ++ decs args in- writeFile output sourceCode--genCTuple :: Args -> Word -> String-genCTuple Args{classNewtype} n- | n == 0 = "CTuple0"- | otherwise = parens (concat (intersperse ", " cNums))- ++ " => CTuple" ++ show n ++ " " ++ unwords cNums- where- parens :: String -> String- parens s | n == 1 = s- | otherwise = kindSig $ "(" ++ s ++ ")"-- kindSig :: String -> String- kindSig s | classNewtype = "(" ++ s ++ " :: Constraint)"- | otherwise = s-- cNums :: [String]- cNums = ['c':show i | i <- [1..n]]--haddocks :: Word -> [String]-haddocks i =- [ "-- | A constraint tuple class with " ++ show i ++ " arguments."- ] ++- if i == 0- then [ "--"- , "-- This class is only defined on GHC 7.8 or later."- ]- else []--maxTupleSize :: Word-maxTupleSize = 62--preamble :: Args -> [String]-preamble Args{classNewtype} =- [ "{-# LANGUAGE ConstraintKinds #-}"- , "{-# LANGUAGE CPP #-}"- , "{-# LANGUAGE FlexibleInstances #-}"- , "{-# LANGUAGE KindSignatures #-}"- , "{-# LANGUAGE MultiParamTypeClasses #-}"- , "{-# LANGUAGE UndecidableInstances #-}"- , "#if __GLASGOW_HASKELL__ >= 708 && __GLASGOW_HASKELL__ < 710"- , "{-# LANGUAGE NullaryTypeClasses #-}"- , "#endif"- , "#if __GLASGOW_HASKELL__ >= 800"- , "{-# LANGUAGE UndecidableSuperClasses #-}"- , "#endif"- ] ++ safeHaskell ++- [ "-- | This module provides classes that emulate the behavior of GHC's constraint"- , "-- tuple syntax. Unlike GHC's built-in constraint tuples, the classes in this"- , "-- library can be partially applied."- , "--"- ] ++ haddockNote ++- [ "module " ++ modName- , " ( -- * Constraint tuples"- ] ++ exports ++- [ " ) where"- , ""- ] ++ imports- where- modName :: String- modName = "Data.Tuple.Constraint" ++- if classNewtype then ".ClassNewtype" else ""-- exports :: [String]- exports = flip concatMap [0..maxTupleSize] $ \i ->- case i of- 0 -> [ "#if __GLASGOW_HASKELL__ >= 708"- , " CTuple0,"- , "#endif"- ]- 1 -> [ " CTuple1" ]- _ -> [ " , CTuple" ++ show i ]-- imports :: [String]- imports | classNewtype- = [ "import Data.Tuple.Constraint ( CTuple1"- , "#if __GLASGOW_HASKELL__ >= 708"- , " , CTuple0"- , "#endif"- , " )"- , "#if __GLASGOW_HASKELL__ >= 800"- , "import Data.Kind (Constraint)"- , "#else"- , "import GHC.Exts (Constraint)"- , "#endif"- , ""- ]- | otherwise- = []-- safeHaskell :: [String]- safeHaskell | classNewtype- = [ "#if __GLASGOW_HASKELL__ >= 800"- , "{-# LANGUAGE Safe #-}"- , "#else"- , "{-# LANGUAGE Trustworthy #-}"- , "#endif"- ]- | otherwise- = [ "{-# LANGUAGE Safe #-}" ]-- haddockNote :: [String]- haddockNote- | classNewtype- = [ "-- Unlike \"Data.Tuple.Constraint\", a @CTupleN@ class defined in this module"- , "-- (where @N@ is greater than 1) compiles to a newtype around the corresponding"- , "-- built-in constraint tuple type with @N@ arguments in Core. In contrast, a"- , "-- @CTupleN@ class defined in \"Data.Tuple.Constraint\" compiles to a"- , "-- dictionary data type with @N@ fields in Core."- , "--"- , "-- For most use cases, this distinction is of no practical consequence. One"- , "-- scenario where you may benefit from using this module is when you are"- , "-- interoperating with built-in constraint tuple syntax."- , "-- For example, in this code:"- , "--"- , "-- @"- , "-- data Dict :: Constraint -> Type where"- , "-- Dict :: c => Dict c"- , "--"- , "-- foo :: CTuple2 a b => Dict (a, b)"- , "-- foo = Dict"- , "-- @"- , "--"- , "-- If you use the @CTuple2@ class from \"Data.Tuple.Constraint\" to define"- , "-- @foo@, then in the Core for @foo@, the @a@ and @b@ must be extracted from"- , "-- the @CTuple2@ dictionary before building the @Dict@ dictionary. On the other"- , "-- hand, if you use the @CTuple@ class from this module, then no such"- , "-- extraction is necessary, as the Core can simply cast the @CTuple2@"- , "-- dictionary (which is a newtype) to the @(a, b)@ dictionary and use that to"- , "-- construct a @Dict@ dictionary."- ]- | otherwise- = []--decs :: Args -> [String]-decs args@Args{classNewtype} =- flip concatMap [0..maxTupleSize] $ \i ->- let cTuple = genCTuple args i in- if classNewtype && (i == 0 || i == 1)- then [] -- CTuple{0,1} are imported from Data.Tuple.Constraint- else concat- [ [ "#if __GLASGOW_HASKELL__ >= 708" | i == 0 ]- , haddocks i- , [ "class " ++ cTuple- , "instance " ++ cTuple- ]- , [ "#endif" | i == 0 ]- , [ "" ]- ]
+ generator-script/LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2018-2019, Ryan Scott++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 Ryan Scott 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.
+ generator-script/exe/GeneratorScript.hs view
@@ -0,0 +1,194 @@+{-# LANGUAGE NamedFieldPuns #-}+-- | The script that generates the source code for "Data.Tuple.Constraint" and+-- "Data.Tuple.Constraint.ClassNewtype". See the @GenCTuple.sh@ script for how+-- to invoke this.+module Main (main) where++import Data.List.Compat+import GHC.Exts (maxTupleSize)+import Prelude ()+import Prelude.Compat+import Options.Applicative++data Args = Args+ { output :: FilePath+ , classNewtype :: Bool+ } deriving Show++argsParser :: Parser Args+argsParser = Args+ <$> strOption+ ( long "output"+ <> short 'o'+ <> metavar "PATH"+ <> help "The file to which to write the source code" )+ <*> switch+ ( long "class-newtype"+ <> help "Generate the source code for Data.Tuple.Constraint.ClassNewtype" )++main :: IO ()+main = execParser opts >>= generate+ where+ opts = info (argsParser <**> helper)+ ( fullDesc+ <> progDesc spiel+ <> header spiel )++ spiel = "Generate the source code for Data.Tuple.Constraint{,.ClassNewtype}"++generate :: Args -> IO ()+generate args@Args{output} =+ let sourceCode = unlines $ preamble args ++ decs args in+ writeFile output sourceCode++genCTuple :: Args -> Int -> String+genCTuple Args{classNewtype} n+ | n == 0 = "CTuple0"+ | otherwise = parens (concat (intersperse ", " cNums))+ ++ " => CTuple" ++ show n ++ " " ++ unwords cNums+ where+ parens :: String -> String+ parens s | n == 1 = s+ | otherwise = kindSig $ "(" ++ s ++ ")"++ kindSig :: String -> String+ kindSig s | classNewtype = "(" ++ s ++ " :: Constraint)"+ | otherwise = s++ cNums :: [String]+ cNums = ['c':show i | i <- [1..n]]++haddocks :: Int -> [String]+haddocks i =+ [ "-- | A constraint tuple class with " ++ show i +++ " argument" ++ pluralSuffix ++ "."+ ] +++ if i == 0+ then [ "--"+ , "-- This class is only defined on GHC 7.8 or later."+ ]+ else []+ where+ pluralSuffix :: String+ pluralSuffix | i == 1+ = ""+ | otherwise+ = "s"++preamble :: Args -> [String]+preamble Args{classNewtype} =+ [ "{-# LANGUAGE ConstraintKinds #-}"+ , "{-# LANGUAGE CPP #-}"+ , "{-# LANGUAGE FlexibleInstances #-}"+ , "{-# LANGUAGE KindSignatures #-}"+ , "{-# LANGUAGE MultiParamTypeClasses #-}"+ , "{-# LANGUAGE UndecidableInstances #-}"+ , "#if __GLASGOW_HASKELL__ >= 708 && __GLASGOW_HASKELL__ < 710"+ , "{-# LANGUAGE NullaryTypeClasses #-}"+ , "#endif"+ , "#if __GLASGOW_HASKELL__ >= 800"+ , "{-# LANGUAGE UndecidableSuperClasses #-}"+ , "#endif"+ ] ++ safeHaskell +++ [ "-- | This module provides classes that emulate the behavior of GHC's constraint"+ , "-- tuple syntax. Unlike GHC's built-in constraint tuples, the classes in this"+ , "-- library can be partially applied."+ , "--"+ ] ++ haddockNote +++ [ "module " ++ modName+ , " ( -- * Constraint tuples"+ ] ++ exports +++ [ " ) where"+ , ""+ ] ++ imports+ where+ modName :: String+ modName = "Data.Tuple.Constraint" +++ if classNewtype then ".ClassNewtype" else ""++ exports :: [String]+ exports = flip concatMap [0..maxTupleSize] $ \i ->+ case i of+ 0 -> [ "#if __GLASGOW_HASKELL__ >= 708"+ , " CTuple0,"+ , "#endif"+ ]+ 1 -> [ " CTuple1" ]+ _ -> [ " , CTuple" ++ show i ]++ imports :: [String]+ imports | classNewtype+ = [ "import Data.Tuple.Constraint ( CTuple1"+ , "#if __GLASGOW_HASKELL__ >= 708"+ , " , CTuple0"+ , "#endif"+ , " )"+ , "#if __GLASGOW_HASKELL__ >= 800"+ , "import Data.Kind (Constraint)"+ , "#else"+ , "import GHC.Exts (Constraint)"+ , "#endif"+ , ""+ ]+ | otherwise+ = []++ safeHaskell :: [String]+ safeHaskell | classNewtype+ = [ "#if __GLASGOW_HASKELL__ >= 800"+ , "{-# LANGUAGE Safe #-}"+ , "#else"+ , "{-# LANGUAGE Trustworthy #-}"+ , "#endif"+ ]+ | otherwise+ = [ "{-# LANGUAGE Safe #-}" ]++ haddockNote :: [String]+ haddockNote+ | classNewtype+ = [ "-- Unlike \"Data.Tuple.Constraint\", a @CTupleN@ class defined in this module"+ , "-- (where @N@ is greater than 1) compiles to a newtype around the corresponding"+ , "-- built-in constraint tuple type with @N@ arguments in Core. In contrast, a"+ , "-- @CTupleN@ class defined in \"Data.Tuple.Constraint\" compiles to a"+ , "-- dictionary data type with @N@ fields in Core."+ , "--"+ , "-- For most use cases, this distinction is of no practical consequence. One"+ , "-- scenario where you may benefit from using this module is when you are"+ , "-- interoperating with built-in constraint tuple syntax."+ , "-- For example, in this code:"+ , "--"+ , "-- @"+ , "-- data Dict :: Constraint -> Type where"+ , "-- Dict :: c => Dict c"+ , "--"+ , "-- foo :: CTuple2 a b => Dict (a, b)"+ , "-- foo = Dict"+ , "-- @"+ , "--"+ , "-- If you use the @CTuple2@ class from \"Data.Tuple.Constraint\" to define"+ , "-- @foo@, then in the Core for @foo@, the @a@ and @b@ must be extracted from"+ , "-- the @CTuple2@ dictionary before building the @Dict@ dictionary. On the other"+ , "-- hand, if you use the @CTuple@ class from this module, then no such"+ , "-- extraction is necessary, as the Core can simply cast the @CTuple2@"+ , "-- dictionary (which is a newtype) to the @(a, b)@ dictionary and use that to"+ , "-- construct a @Dict@ dictionary."+ ]+ | otherwise+ = []++decs :: Args -> [String]+decs args@Args{classNewtype} =+ flip concatMap [0..maxTupleSize] $ \i ->+ let cTuple = genCTuple args i in+ if classNewtype && (i == 0 || i == 1)+ then [] -- CTuple{0,1} are imported from Data.Tuple.Constraint+ else concat+ [ [ "#if __GLASGOW_HASKELL__ >= 708" | i == 0 ]+ , haddocks i+ , [ "class " ++ cTuple+ , "instance " ++ cTuple+ ]+ , [ "#endif" | i == 0 ]+ , [ "" ]+ ]
+ generator-script/generator-script.cabal view
@@ -0,0 +1,40 @@+cabal-version: >=1.10+name: generator-script+version: 0.1+synopsis: Generate constraint-tuples' source code+description: The script that generates the source code for+ "Data.Tuple.Constraint" and+ "Data.Tuple.Constraint.ClassNewtype". See the+ @GenCTuple.sh@ script for how to invoke this.+homepage: https://github.com/RyanGlScott/constraint-tuples+bug-reports: https://github.com/RyanGlScott/constraint-tuples/issues+license: BSD3+license-file: LICENSE+author: Ryan Scott+maintainer: ryan.gl.scott@gmail.com+stability: Stable+copyright: (C) 2018-2019 Ryan Scott+category: Data+build-type: Simple+tested-with: GHC == 7.6.3+ , GHC == 7.8.4+ , GHC == 7.10.3+ , GHC == 8.0.2+ , GHC == 8.2.2+ , GHC == 8.4.4+ , GHC == 8.6.5+ , GHC == 8.8.1++source-repository head+ type: git+ location: https://github.com/RyanGlScott/constraint-tuples+ subdir: generator-script++executable generator-script+ main-is: GeneratorScript.hs+ build-depends: base >= 4.6 && < 5+ , base-compat-batteries >= 0.10 && < 0.12+ , optparse-applicative >= 0.13 && < 0.16+ hs-source-dirs: exe+ default-language: Haskell2010+ ghc-options: -Wall -threaded -rtsopts
src/Data/Tuple/Constraint.hs view
@@ -92,7 +92,7 @@ instance CTuple0 #endif --- | A constraint tuple class with 1 arguments.+-- | A constraint tuple class with 1 argument. class c1 => CTuple1 c1 instance c1 => CTuple1 c1