Skip to content

Commit 784a43a

Browse files
authored
Merge pull request #7046 from phadej/newtype-nonempty
Add alaNonEmpty
2 parents e0c2cef + 5b9bf62 commit 784a43a

File tree

1 file changed

+52
-4
lines changed

1 file changed

+52
-4
lines changed

Cabal/src/Distribution/FieldGrammar/Newtypes.hs

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,14 @@ module Distribution.FieldGrammar.Newtypes (
1818
Sep (..),
1919
-- ** Type
2020
List,
21-
-- * Set
21+
-- ** Set
2222
alaSet,
2323
alaSet',
2424
Set',
25+
-- ** NonEmpty
26+
alaNonEmpty,
27+
alaNonEmpty',
28+
NonEmpty',
2529
-- * Version & License
2630
SpecVersion (..),
2731
TestedWith (..),
@@ -46,6 +50,7 @@ import Distribution.Version
4650
(LowerBound (..), Version, VersionRange, VersionRangeF (..), anyVersion, asVersionIntervals, cataVersionRange, mkVersion, version0, versionNumbers)
4751
import Text.PrettyPrint (Doc, comma, fsep, punctuate, text, vcat)
4852

53+
import qualified Data.List.NonEmpty as NE
4954
import qualified Data.Set as Set
5055
import qualified Distribution.Compat.CharParsing as P
5156
import qualified Distribution.SPDX as SPDX
@@ -68,31 +73,41 @@ data NoCommaFSep = NoCommaFSep
6873
class Sep sep where
6974
prettySep :: Proxy sep -> [Doc] -> Doc
7075

71-
parseSep :: CabalParsing m => Proxy sep -> m a -> m [a]
76+
parseSep :: CabalParsing m => Proxy sep -> m a -> m [a]
77+
parseSepNE :: CabalParsing m => Proxy sep -> m a -> m (NonEmpty a)
7278

7379
instance Sep CommaVCat where
7480
prettySep _ = vcat . punctuate comma
7581
parseSep _ p = do
7682
v <- askCabalSpecVersion
7783
if v >= CabalSpecV2_2 then parsecLeadingCommaList p else parsecCommaList p
84+
parseSepNE _ p = do
85+
v <- askCabalSpecVersion
86+
if v >= CabalSpecV2_2 then parsecLeadingCommaNonEmpty p else parsecCommaNonEmpty p
7887
instance Sep CommaFSep where
7988
prettySep _ = fsep . punctuate comma
8089
parseSep _ p = do
8190
v <- askCabalSpecVersion
8291
if v >= CabalSpecV2_2 then parsecLeadingCommaList p else parsecCommaList p
92+
parseSepNE _ p = do
93+
v <- askCabalSpecVersion
94+
if v >= CabalSpecV2_2 then parsecLeadingCommaNonEmpty p else parsecCommaNonEmpty p
8395
instance Sep VCat where
8496
prettySep _ = vcat
8597
parseSep _ p = do
8698
v <- askCabalSpecVersion
8799
if v >= CabalSpecV3_0 then parsecLeadingOptCommaList p else parsecOptCommaList p
100+
parseSepNE _ p = NE.some1 (p <* P.spaces)
88101
instance Sep FSep where
89102
prettySep _ = fsep
90103
parseSep _ p = do
91104
v <- askCabalSpecVersion
92105
if v >= CabalSpecV3_0 then parsecLeadingOptCommaList p else parsecOptCommaList p
106+
parseSepNE _ p = NE.some1 (p <* P.spaces)
93107
instance Sep NoCommaFSep where
94-
prettySep _ = fsep
95-
parseSep _ p = many (p <* P.spaces)
108+
prettySep _ = fsep
109+
parseSep _ p = many (p <* P.spaces)
110+
parseSepNE _ p = NE.some1 (p <* P.spaces)
96111

97112
-- | List separated with optional commas. Displayed with @sep@, arguments of
98113
-- type @a@ are parsed and pretty-printed as @b@.
@@ -158,6 +173,39 @@ instance (Newtype a b, Ord a, Sep sep, Parsec b) => Parsec (Set' sep b a) where
158173
instance (Newtype a b, Sep sep, Pretty b) => Pretty (Set' sep b a) where
159174
pretty = prettySep (Proxy :: Proxy sep) . map (pretty . (pack :: a -> b)) . Set.toList . unpack
160175

176+
--
177+
-- | Like 'List', but for 'NonEmpty'.
178+
--
179+
-- @since 3.2.0.0
180+
newtype NonEmpty' sep b a = NonEmpty' { _getNonEmpty :: NonEmpty a }
181+
182+
-- | 'alaNonEmpty' and 'alaNonEmpty'' are simply 'NonEmpty'' constructor, with additional phantom
183+
-- arguments to constrain the resulting type
184+
--
185+
-- >>> :t alaNonEmpty VCat
186+
-- alaNonEmpty VCat :: NonEmpty a -> NonEmpty' VCat (Identity a) a
187+
--
188+
-- >>> unpack' (alaNonEmpty' FSep Token) <$> eitherParsec "foo bar foo"
189+
-- Right ("foo" :| ["bar","foo"])
190+
--
191+
-- @since 3.2.0.0
192+
alaNonEmpty :: sep -> NonEmpty a -> NonEmpty' sep (Identity a) a
193+
alaNonEmpty _ = NonEmpty'
194+
195+
-- | More general version of 'alaNonEmpty'.
196+
--
197+
-- @since 3.2.0.0
198+
alaNonEmpty' :: sep -> (a -> b) -> NonEmpty a -> NonEmpty' sep b a
199+
alaNonEmpty' _ _ = NonEmpty'
200+
201+
instance Newtype (NonEmpty a) (NonEmpty' sep wrapper a)
202+
203+
instance (Newtype a b, Sep sep, Parsec b) => Parsec (NonEmpty' sep b a) where
204+
parsec = pack . fmap (unpack :: b -> a) <$> parseSepNE (Proxy :: Proxy sep) parsec
205+
206+
instance (Newtype a b, Sep sep, Pretty b) => Pretty (NonEmpty' sep b a) where
207+
pretty = prettySep (Proxy :: Proxy sep) . map (pretty . (pack :: a -> b)) . NE.toList . unpack
208+
161209
-------------------------------------------------------------------------------
162210
-- Identifiers
163211
-------------------------------------------------------------------------------

0 commit comments

Comments
 (0)