packages feed

OneTuple 0.2.2.1 → 0.4.3

raw patch · 7 files changed

Files

Changelog.md view
@@ -1,4 +1,34 @@-# next+# 0.4.3++- Use automatic flags for compatibility conditionals++# 0.4.1.1++- Support GHC-7.2 and GHC-7.0.++# 0.4.1++- Mark `MkSolo` pattern synonym as `COMPLETE`++# 0.4++- Rename constructor to `MkSolo` as in `base-4.17`.+  The compatibility pattern synonym is provided.+- Add `Foldable1 Solo` instance++# 0.3.1++- Add `Data.Tuple.Solo.TH` with `tupE` using `Solo` from this package+- Add `Hashable` and `Hashable1` instances+- Drop GHC-7.0 and GHC-7.2 support++# 0.3++- Rename `OneTuple` to `Solo`+- Add `Typeable`, `Data`, `MonadZip`, `Eq1`, `Ord1`, `Show1`, `Read1`,+  `Generic` and `Generic1` instances++# 0.2.2.1  - Compatible with GHC-8.6 
OneTuple.cabal view
@@ -1,14 +1,16 @@-cabal-version:      >=1.10+cabal-version:      1.12 name:               OneTuple-version:            0.2.2.1+version:            0.4.3 synopsis:           Singleton Tuple category:           Data description:-  This package provides a singleton tuple data type+  This package is a compatibility package for a singleton data type   .-  > data OneTuple a = OneTuple a+  > data Solo a = MkSolo a   .   Note: it's not a @newtype@+  .+  @Solo@ is available in @base-4.16@ (GHC-9.2).  copyright:          (c) John Dorsey 2008 license:            BSD3@@ -20,18 +22,17 @@ stability:          experimental build-type:         Simple tested-with:-  GHC ==7.0.4-   || ==7.2.2-   || ==7.4.2-   || ==7.6.3-   || ==7.8.4-   || ==7.10.3-   || ==8.0.2-   || ==8.2.2-   || ==8.4.4-   || ==8.6.5-   || ==8.8.3-   || ==8.10.1+  GHC ==8.6.5+   || ==8.8.4+   || ==8.10.7+   || ==9.0.2+   || ==9.2.8+   || ==9.4.8+   || ==9.6.4+   || ==9.8.6+   || ==9.10.2+   || ==9.12.2+   || ==9.14.1  extra-source-files: Changelog.md @@ -39,11 +40,77 @@   type:     git   location: https://github.com/phadej/OneTuple.git +flag base-ge-4-15+  description: @base >=4.15@ (GHC-9.0)+  default:     True+  manual:      False++flag base-ge-4-16+  description: @base >=4.16@ (GHC-9.2)+  default:     True+  manual:      False+ library   default-language: Haskell98-  exposed-modules:  Data.Tuple.OneTuple+  exposed-modules:+    Data.Tuple.OneTuple+    Data.Tuple.Solo+    Data.Tuple.Solo.TH+   hs-source-dirs:   src-  build-depends:    base >=4.3 && <4.15+  build-depends:+      base              >=4.12 && <4.23+    , template-haskell +  if flag(base-ge-4-15)+    build-depends: ghc-prim++  else+    build-depends: hashable >=1.3.5.0 && <1.6++  if !flag(base-ge-4-15)+    build-depends: foldable1-classes-compat >=0.1 && <0.2++  if !flag(base-ge-4-16)+    build-depends: base-orphans >=0.8.6++  -- flag selection forcing conditionals+  if flag(base-ge-4-15)+    build-depends: base >=4.15++  else+    build-depends: base <4.15++  if flag(base-ge-4-16)+    build-depends: base >=4.16++  else+    build-depends: base <4.16++test-suite instances+  type:             exitcode-stdio-1.0+  default-language: Haskell98+  hs-source-dirs:   test+  main-is:          instances.hs+  build-depends:+      base+    , hashable+    , OneTuple+   if !impl(ghc >=8.0)-    build-depends: semigroups >=0.18.4 && <0.20+    build-depends:+        semigroups+      , transformers+      , transformers-compat++  if !impl(ghc >=9.6)+    build-depends: foldable1-classes-compat >=0.1 && <0.2++test-suite th+  type:             exitcode-stdio-1.0+  default-language: Haskell98+  hs-source-dirs:   test+  main-is:          th.hs+  build-depends:+      base+    , OneTuple
src/Data/Tuple/OneTuple.hs view
@@ -1,85 +1,24 @@--- |OneTuple fills the /tuple gap/ with a singleton tuple.------ OneTuple /does not support/ the usual parenthesized tuple syntax.------ OneTuple------   * has the expected laziness properties------   * can be pattern-matched------   * ships with instances for several standard type classes,---     including all those supported by H98-standard tuples+{-# LANGUAGE PatternSynonyms #-}+-- | This is a module to help migration from @OneTuple@ to @Solo@.+-- Migrate to use "Data.Tuple" from @base-4.16@ or "Data.Tuple.Solo" with all GHCs. -----   * requires no language extensions, except for hierarchical modules--module Data.Tuple.OneTuple (OneTuple(OneTuple), only) where--import Control.Applicative (Applicative (..))-import Control.Monad       (ap)-import Control.Monad.Fix   (MonadFix (..))-import Data.Foldable       (Foldable (..))-import Data.Ix             (Ix (..))-import Data.Monoid         (Monoid (..))-import Data.Semigroup      (Semigroup (..))-import Data.Traversable    (Traversable (..))---- |OneTuple is the singleton tuple data type.-data OneTuple a-    = OneTuple a  -- ^ singleton tuple constructor-    deriving (Eq,Ord,Bounded,Show,Read)---- |The 'only' function extracts the OneTuple's only member.--- (Compare to 'fst' and 'snd'.)-only :: OneTuple a -- ^ takes a singleton tuple argument-     -> a          -- ^ returns the only element in the tuple-only (OneTuple x) = x--instance (Enum a) => Enum (OneTuple a) where-    succ = fmap succ-    pred = fmap pred-    toEnum = pure . toEnum-    fromEnum (OneTuple x) = fromEnum x--instance (Ix a) => Ix (OneTuple a) where-    range   (OneTuple x, OneTuple y) = map OneTuple (range (x,y))-    index   (OneTuple x, OneTuple y) (OneTuple z) = index   (x,y) z-    inRange (OneTuple x, OneTuple y) (OneTuple z) = inRange (x,y) z--instance Foldable OneTuple where-    fold (OneTuple m) = m-    foldMap f (OneTuple x) = f x-    foldr f b (OneTuple x) = f x b-    foldl f a (OneTuple x) = f a x-    foldr1 _f (OneTuple x) = x-    foldl1 _f (OneTuple x) = x--instance Traversable OneTuple where-    traverse f (OneTuple x) = fmap OneTuple (f x)-    sequenceA (OneTuple x) = fmap OneTuple x--instance Functor OneTuple where-    fmap f (OneTuple x) = OneTuple (f x)--instance Applicative OneTuple where-    pure = OneTuple--    OneTuple f <*> OneTuple x = OneTuple (f x)-    _ *> x = x-    x <* _ = x+-- The pattern synonym is provided for GHCs supporting pattern synonyms (7.8+)+module Data.Tuple.OneTuple+{-# DEPRECATED "Use Data.Tuple.Solo" #-}+(+    OneTuple,+    pattern OneTuple,+    only,+) where -instance Monad OneTuple where-    return = pure-    (>>) = (*>)-    (OneTuple x) >>= f = f x+import Data.Tuple.Solo -instance (Semigroup a) => Semigroup (OneTuple a) where-    OneTuple x <> OneTuple y = OneTuple (x <> y)+type OneTuple = Solo -instance (Monoid a) => Monoid (OneTuple a) where-    mempty = OneTuple mempty-    mappend (OneTuple x) (OneTuple y) = OneTuple (mappend x y)+only :: OneTuple a -> a+only = getSolo -instance MonadFix OneTuple where-    mfix f = let a = f (only a) in a+pattern OneTuple :: a -> Solo a+pattern OneTuple a = MkSolo a +{-# COMPLETE OneTuple #-}
+ src/Data/Tuple/Solo.hs view
@@ -0,0 +1,200 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE Safe #-}++-- | 'Solo' fills the /tuple gap/ with a singleton tuple.+--+-- 'Solo' /does not support/ the usual parenthesized tuple syntax.+--+-- 'Solo'+--+--   * has the expected laziness properties+--+--   * can be pattern-matched+--+--   * ships with instances for several standard type classes,+--     including all those supported by H98-standard tuples+--+--   * requires no language extensions, except for hierarchical modules+--+-- Note: on GHC-9.0 'getSolo' is not a record selector.++module Data.Tuple.Solo (+    Solo(MkSolo,Solo),+    getSolo,+) where++#ifdef MIN_VERSION_base_orphans+import Data.Orphans ()+#endif++#if MIN_VERSION_base(4,18,0)+import GHC.Tuple (Solo (MkSolo, Solo), getSolo)+++#elif MIN_VERSION_base(4,16,0)+import GHC.Tuple (Solo (Solo), getSolo)++pattern MkSolo :: a -> Solo a+pattern MkSolo a = Solo a++{-# COMPLETE MkSolo #-}++#elif MIN_VERSION_base(4,15,0)+import GHC.Tuple (Solo (Solo))++-- | The 'getSolo' function extracts the Solo's getSolo member.+getSolo :: Solo a -> a+getSolo (Solo x) = x++pattern MkSolo :: a -> Solo a+pattern MkSolo a = Solo a++{-# COMPLETE MkSolo #-}++-- !MIN_VERSION_base(4,15,0)+#else++import Control.Applicative (Applicative (..))+import Control.Monad       (ap)+import Control.Monad.Fix   (MonadFix (..))+import Data.Data           (Data)+import Data.Foldable       (Foldable (..))+import Data.Ix             (Ix (..))+import Data.List.NonEmpty  (NonEmpty (..))+import Data.Monoid         (Monoid (..))+import Data.Semigroup      (Semigroup (..))+import Data.Traversable    (Traversable (..))+import Data.Typeable       (Typeable)++import qualified Data.Foldable1 as F1++import Data.Functor.Classes (Eq1 (..), Ord1 (..), Show1 (..), Read1 (..))++#if !(MIN_VERSION_base(4,15,0))+import Data.Hashable        (Hashable (..))+import Data.Hashable.Lifted (Hashable1 (..), hashWithSalt1)+#endif++import Data.Functor.Classes (readData, readUnaryWith, liftReadListDefault, liftReadListPrecDefault)+import GHC.Generics        (Generic, Generic1)+import Control.Monad.Zip   (MonadZip (..))++-- | Solo is the singleton tuple data type.+data Solo a = MkSolo { getSolo :: a }+  deriving+    ( Eq,Ord,Bounded,Read,Typeable,Data+    , Generic+    , Generic1+    )++pattern Solo :: a -> Solo a+pattern Solo a = MkSolo a+{-# COMPLETE Solo #-}+++instance Show a => Show (Solo a) where+  showsPrec d (MkSolo x) = showParen (d > 10) $+      showString "MkSolo " . showsPrec 11 x++instance (Enum a) => Enum (Solo a) where+    succ = fmap succ+    pred = fmap pred+    toEnum = pure . toEnum+    fromEnum (MkSolo x) = fromEnum x++instance (Ix a) => Ix (Solo a) where+    range   (MkSolo x, MkSolo y) = map MkSolo (range (x,y))+    index   (MkSolo x, MkSolo y) (MkSolo z) = index   (x,y) z+    inRange (MkSolo x, MkSolo y) (MkSolo z) = inRange (x,y) z++instance Foldable Solo where+    fold (MkSolo m) = m+    foldMap f (MkSolo x) = f x+    foldr f b (MkSolo x) = f x b+    foldl f a (MkSolo x) = f a x+    foldr1 _f (MkSolo x) = x+    foldl1 _f (MkSolo x) = x++    -- TODO: add rest of the methods+    null _ = False+    length _ = 1++    maximum = getSolo+    minimum = getSolo+    sum     = getSolo+    product = getSolo++    toList (MkSolo a) = [a]++-- | @since 0.4+instance F1.Foldable1 Solo where+    foldMap1 f (MkSolo y) = f y+    toNonEmpty (MkSolo x) = x :| []+    minimum (MkSolo x) = x+    maximum (MkSolo x) = x+    head (MkSolo x) = x+    last (MkSolo x) = x++instance Traversable Solo where+    traverse f (MkSolo x) = fmap MkSolo (f x)+    sequenceA (MkSolo x) = fmap MkSolo x++instance Functor Solo where+    fmap f (MkSolo x) = MkSolo (f x)++instance Applicative Solo where+    pure = MkSolo++    MkSolo f <*> MkSolo x = MkSolo (f x)+    _ *> x = x+    x <* _ = x++    liftA2 f (Solo x) (Solo y) = Solo (f x y)++instance Monad Solo where+    return = pure+    (>>) = (*>)+    MkSolo x >>= f = f x++instance Semigroup a => Semigroup (Solo a) where+    MkSolo x <> MkSolo y = MkSolo (x <> y)++instance Monoid a => Monoid (Solo a) where+    mempty = MkSolo mempty+    mappend (MkSolo x) (MkSolo y) = MkSolo (mappend x y)++instance MonadFix Solo where+    mfix f = let a = f (getSolo a) in a++instance MonadZip Solo where+    mzipWith f (MkSolo a) (MkSolo b) = MkSolo (f a b)++instance Eq1 Solo where+  liftEq eq (MkSolo a) (MkSolo b) = a `eq` b++instance Ord1 Solo where+  liftCompare cmp (MkSolo a) (MkSolo b) = cmp a b++instance Read1 Solo where+    liftReadPrec rp _ = readData (readUnaryWith rp "MkSolo" MkSolo)++    liftReadListPrec = liftReadListPrecDefault+    liftReadList     = liftReadListDefault++instance Show1 Solo where+    liftShowsPrec sp _ d (MkSolo x) = showParen (d > 10) $+      showString "MkSolo " . sp 11 x+#endif++#if !(MIN_VERSION_base(4,15,0))+-- | @since 0.3.1+instance Hashable a => Hashable (Solo a) where+    hashWithSalt = hashWithSalt1++-- | @since 0.3.1+instance Hashable1 Solo where+    liftHashWithSalt h salt (MkSolo a) = h salt a+#endif
+ src/Data/Tuple/Solo/TH.hs view
@@ -0,0 +1,44 @@+{-# LANGUAGE CPP #-}+#if __GLASGOW_HASKELL__ >= 800+{-# LANGUAGE TemplateHaskellQuotes #-}+#endif+-- | This module provides TH helpers,+-- which use 'Solo' from this package, for 1-tuples.+module Data.Tuple.Solo.TH (+    tupE,+) where+++#if MIN_VERSION_template_haskell(2,17,0)+import Language.Haskell.TH (tupE)+#else+import Data.Tuple.Solo++import qualified Language.Haskell.TH as TH+import qualified Language.Haskell.TH.Syntax as TH++makeTup :: [TH.Exp] -> TH.Exp+makeTup [x] = TH.AppE (TH.ConE soloConName) x+#if MIN_VERSION_template_haskell(2,16,0)+makeTup xs  = TH.TupE (map Just xs)+#else+makeTup xs  = TH.TupE xs+#endif++soloConName :: TH.Name+#if __GLASGOW_HASKELL__ >= 800+soloConName = 'Solo+#else+#ifndef CURRENT_PACKAGE_KEY +#error "CURRENT_PACKAGE_KEY undefined"+#endif++soloConName = TH.mkNameG_d CURRENT_PACKAGE_KEY "Data.Tuple.Solo" "MkSolo"+#endif++tupE :: Monad m => [m TH.Exp] -> m TH.Exp+tupE xs = do+    xs' <- sequence xs+    return (makeTup xs')+#endif+
+ test/instances.hs view
@@ -0,0 +1,74 @@+{-# LANGUAGE CPP #-}+{-# OPTIONS_GHC -Wincomplete-patterns -Werror=incomplete-patterns #-}+{-# OPTIONS_GHC -fwarn-incomplete-patterns -Werror #-}+module Main where++import Control.Applicative  (Applicative (..))+import Control.Monad.Fix    (MonadFix (..))+import Data.Data            (Data)+import Data.Foldable        (Foldable (..))+import Data.Foldable1       (Foldable1)+import Data.Functor.Classes (Eq1, Ord1, Read1, Show1)+import Data.Hashable        (Hashable)+import Data.Hashable.Lifted (Hashable1)+import Data.Ix              (Ix)+import Data.Monoid          (Monoid (..))+import Data.Semigroup       (Semigroup (..))+import Data.Traversable     (Traversable (..))++#if MIN_VERSION_base(4,4,0)+import Control.Monad.Zip (MonadZip (..))+#endif++import Data.Tuple.Solo (Solo (..))++main :: IO ()+main = putStrLn "works"++-------------------------------------------------------------------------------+-- pattern match+-------------------------------------------------------------------------------++match :: Solo a -> a+match (MkSolo x) = x++-------------------------------------------------------------------------------+-- Instances+-------------------------------------------------------------------------------++tup1 :: Solo Char+tup1 = MkSolo 'x'++tup2 :: Solo String+tup2 = MkSolo "test"++hasEq :: Eq a => a -> a; hasEq x = x; testEq = hasEq tup1+hasOrd :: Ord a => a -> a; hasOrd x = x; testOrd = hasOrd tup1+hasBounded :: Bounded a => a -> a; hasBounded x = x; testBounded = hasBounded tup1+hasEnum :: Enum a => a -> a; hasEnum x = x; testEnum = hasEnum tup1+hasShow :: Show a => a -> a; hasShow x = x; testShow = hasShow tup1+hasRead :: Read a => a -> a; hasRead x = x; testRead = hasRead tup1+hasIx :: Ix a => a -> a; hasIx x = x; testIx = hasIx tup1++hasMonoid :: Monoid a => a -> a; hasMonoid x = x; testMonoid = hasMonoid tup2+hasSemigroup :: Semigroup a => a -> a; hasSemigroup x = x; testSemigroup = hasSemigroup tup2++hasData :: Data a => a -> a; hasData x = x; testData = hasData tup2++hasFunctor :: Functor f => f a -> f a; hasFunctor x = x; testFunctor = hasFunctor tup1+hasFoldable :: Foldable f => f a -> f a; hasFoldable x = x; testFoldable = hasFoldable tup1+hasFoldable1 :: Foldable1 f => f a -> f a; hasFoldable1 x = x; testFoldable1 = hasFoldable1 tup1+hasTraversable :: Traversable f => f a -> f a; hasTraversable x = x; testTraversable = hasTraversable tup1+hasApplicative :: Applicative f => f a -> f a; hasApplicative x = x; testApplicative = hasApplicative tup1+hasMonad :: Monad f => f a -> f a; hasMonad x = x; testMonad = hasMonad tup1+hasMonadFix :: MonadFix f => f a -> f a; hasMonadFix x = x; testMonadFix = hasMonadFix tup1++hasMonadZip :: MonadZip f => f a -> f a; hasMonadZip x = x; testMonadZip = hasMonadZip tup1++hasEq1 :: Eq1 f => f a -> f a; hasEq1 x = x; testEq1 = hasEq1 tup1+hasOrd1 :: Ord1 f => f a -> f a; hasOrd1 x = x; testOrd1 = hasOrd1 tup1+hasShow1 :: Show1 f => f a -> f a; hasShow1 x = x; testShow1 = hasShow1 tup1+hasRead1 :: Read1 f => f a -> f a; hasRead1 x = x; testRead1 = hasRead1 tup1++hasHashable :: Hashable a => a -> a; hasHashable x = x; testHashable = hasHashable tup1+hasHashable1 :: Hashable1 f => f a -> f a; hasHashable1 x = x; testHashable1 = hasHashable1 tup1
+ test/th.hs view
@@ -0,0 +1,8 @@+{-# LANGUAGE TemplateHaskell #-}+module Main where++import Data.Tuple.Solo+import Data.Tuple.Solo.TH (tupE)++main :: IO ()+main = print $ MkSolo 'x' == $(tupE [[| 'x' |]])