packages feed

unpacked-maybe (empty) → 0.1.0.0

raw patch · 5 files changed

+779/−0 lines, 5 filesdep +QuickCheckdep +basedep +ghc-primsetup-changed

Dependencies added: QuickCheck, base, ghc-prim, quickcheck-classes, unpacked-maybe

Files

+ LICENSE view
@@ -0,0 +1,29 @@+Copyright © 2016 Kyle McKean+Copyright © 2018chessai++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 Kyle McKean 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.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ src/Data/Maybe/Unpacked.hs view
@@ -0,0 +1,620 @@+--------------------------------------------------------------------------------++-- Copyright © 2016 Kyle McKean+-- Copyright © 2018 Daniel Cartwright++-- 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 Kyle McKean 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.++--------------------------------------------------------------------------------++{-# OPTIONS_GHC -Wall #-}++--------------------------------------------------------------------------------++{-# LANGUAGE BangPatterns       #-}+{-# LANGUAGE PatternSynonyms    #-}+{-# LANGUAGE UnboxedSums        #-}+{-# LANGUAGE UnboxedTuples      #-}++--------------------------------------------------------------------------------++{-| This module is intended to be a drop-in replacement+    for base's 'Data.Maybe'. To shave off pointer chasing, it+    uses @'-XUnboxedSums'@ to represent the @'Maybe'@ type+    as two machine words that are contiguous in memory, without+    loss of expressiveness that base's 'Data.Maybe' provides.++    This library provides pattern synonyms @'Just'@ and @'Nothing'@+    that allow users to pattern match on an unpacked Maybe+    in a familiar way.++    Functions are also provided for converting an unpacked Maybe+    to the base library's Maybe, and vice versa.++    This library is in alpha, and the internals+    are likely to change.+-}++module Data.Maybe.Unpacked+  ( Maybe(Maybe, Just, Nothing)+  , nothing+  , just+  , maybe+  , isJust+  , isNothing+  , fromJust+  , fromMaybe+  , listToMaybe+  , maybeToList+  , catMaybes+  , mapMaybe+  , fromBaseMaybe+  , toBaseMaybe+  ) where++--------------------------------------------------------------------------------++import Prelude+  ()++import           Control.Applicative (Alternative(empty, (<|>)), Applicative(liftA2, pure, (<*>), (*>)))++import           Control.Monad       (Monad(return, (>>=)), MonadPlus(mzero, mplus))+import           Control.Monad.Fail  (MonadFail(fail))+import           Control.Monad.Fix   (MonadFix(mfix))+import           Control.Monad.Zip   (MonadZip(mzipWith))++import           Data.Data+  ( Constr+  , Data(dataTypeOf, gunfold, toConstr) +  , DataType+  , Fixity(Prefix)+  , mkConstr+  , mkDataType+  )+import           Data.Eq             (Eq((==)))+import           Data.Foldable+  (Foldable(foldMap, foldr, foldl, length, null, product, sum))++import           Data.Function       (const, flip, id, (.), ($))+import           Data.Functor        (Functor(fmap))+import           Data.Functor.Classes+  ( Eq1(liftEq)+  , Ord1(liftCompare)+  , Read1(liftReadPrec, liftReadListPrec, liftReadList)+  , Show1(liftShowsPrec)+  , readData+  , readUnaryWith+  , liftReadListPrecDefault+  , liftReadListDefault+  , showsUnaryWith+  )++import qualified Data.Maybe          as BaseMaybe+import           Data.Monoid         (Monoid(mempty,mappend))+import           Data.Ord            (Ord(compare, (>)), Ordering(EQ, GT, LT))+import           Data.Semigroup      (Semigroup((<>)))+import           Data.Traversable    (Traversable(sequenceA, traverse))++import           GHC.Base            (Bool(False,True), Int, build)+import           GHC.Err             (error, errorWithoutStackTrace)+import           GHC.Num             ( (+) )+import           GHC.Read            (Read(readPrec), expectP)+import           GHC.Show            (Show(showsPrec), showString, showParen)++import           Text.Read           (parens, Lexeme(Ident), lexP, (+++))+import           Text.ParserCombinators.ReadPrec (prec, step)++--------------------------------------------------------------------------------++-- | The 'Maybe' type encapsulates an optional value.  A value of type+-- @'Maybe' a@ either contains a value of type @a@ (represented as @'Just' a@),+-- or it is empty (represented as @'Nothing'@).  Using 'Maybe' is a good way to+-- deal with errors or exceptional cases without resorting to drastic+-- measures such as 'error'.+--+-- The 'Maybe' type is also a monad.  It is a simple kind of error+-- monad, where all errors are represented by @'Nothing'@.  A richer+-- error monad can be built using the 'Data.Either.Either' type.+--+data Maybe a = Maybe (# (# #) | a #)++-- | The 'Just' pattern synonym mimics the functionality of the 'Data.Maybe.Just' constructor+--   from /Data.Maybe/.+--+pattern Just :: a -> Maybe a+pattern Just a = Maybe (# | a #)++-- | The 'Nothing' pattern synonym mimics the functionality of the 'Data.Maybe.Nothing' constructor+--   from /Data.Maybe/.+-- +pattern Nothing :: Maybe a+pattern Nothing = Maybe (# (# #) | #)++{-# COMPLETE Just, Nothing #-}++-- | This is the same as 'Nothing'.+nothing :: Maybe a+nothing = Maybe (# (# #) | #)+{-# INLINE nothing #-}++-- | This is the same as 'Just'.+just :: a -> Maybe a+just x = Maybe (# | x #)+{-# INLINE just #-}++-- | The 'maybe' function takes a default value, a function, and a 'Maybe'+-- value.  If the 'Maybe' value is 'Nothing', the function returns the+-- default value.  Otherwise, it applies the function to the value inside+-- the 'Just' and returns the result.+--+-- ==== __Examples__+--+-- Basic usage:+--+-- >>> maybe False odd (just 3)+-- True+--+-- >>> maybe False odd nothing+-- False+--+-- Read an integer from a string using 'readMaybe'. If we succeed,+-- return twice the integer; that is, apply @(*2)@ to it. If instead+-- we fail to parse an integer, return @0@ by default:+--+-- >>> maybe 0 (*2) (fromBaseMaybe $ readMaybe "5")+-- 10+-- >>> maybe 0 (*2) (fromBaseMaybe $ readMaybe "")+-- 0+--+-- Apply 'show' to a @Maybe Int@. If we have @'just' n@, we want to show+-- the underlying 'Int' @n@. But if we have 'nothing', we return the+-- empty string instead of (for example) \"Nothing\":+--+-- >>> maybe "" show (just 5)+-- "5"+-- >>> maybe "" show nothing+-- ""+--+maybe :: b -> (a -> b) -> Maybe a -> b+maybe def f (Maybe x) = case x of+  (# (# #) |   #) -> def+  (#       | a #) -> f a+{-# INLINE maybe #-}++-- | The 'isJust' function returns 'True' if its argument is of the+-- form @Just _@.+--+-- ==== __Examples__+--+-- Basic usage:+--+-- >>> isJust (just 3)+-- True+--+-- >>> isJust (just ())+-- True+--+-- >>> isJust nothing+-- False+--+-- Only the outer constructor is taken into consideration:+--+-- >>> isJust (just nothing)+-- True+--+isJust :: Maybe a -> Bool+isJust = maybe False (const True)+{-# INLINE isJust #-}++-- | The 'isNothing' function returns 'True' if its argument is 'nothing'.+--+-- ==== __Examples__+--+-- Basic usage:+--+-- >>> isNothing (just 3)+-- False+--+-- >>> isNothing (just ())+-- False+--+-- >>> isNothing nothing+-- True+--+-- Only the outer constructor is taken into consideration:+--+-- >>> isNothing (just nothing)+-- False+isNothing :: Maybe a -> Bool+isNothing = maybe True (const False)+{-# INLINE isNothing #-}++-- | The 'fromJust' function extracts the element out of a 'just' and+-- throws an error if its argument is 'nothing'.+--+-- ==== __Examples__+--+-- Basic usage:+--+-- >>> fromJust (just 1)+-- 1+--+-- >>> 2 * (fromJust (just 10))+-- 20+--+-- >>> 2 * (fromJust nothing)+-- *** Exception: Data.Maybe.Unpacked.fromJust: Nothing+--+fromJust :: Maybe a -> a+fromJust = fromMaybe (error "Data.Maybe.Unpacked.fromJust: Nothing")+{-# INLINE fromJust #-}++-- | The 'fromMaybe' function takes a default value and and 'Maybe'+-- value.  If the 'Maybe' is 'nothing', it returns the default values;+-- otherwise, it returns the value contained in the 'Maybe'.+--+-- ==== __Examples__+--+-- Basic usage:+--+-- >>> fromMaybe "" (just "Hello, World!")+-- "Hello, World!"+--+-- >>> fromMaybe "" nothing+-- ""+--+-- Read an integer from a string using 'readMaybe'. If we fail to+-- parse an integer, we want to return @0@ by default:+--+-- >>> import Text.Read ( readMaybe )+-- >>> let parse = fromBaseMaybe . readMaybe :: String -> Maybe Int+-- >>> fromMaybe 0 (parse "5")+-- 5+-- >>> fromMaybe 0 (parse "")+-- 0+--+fromMaybe :: a -> Maybe a -> a+fromMaybe def = maybe def id+{-# INLINE fromMaybe #-}++-- | The 'maybeToList' function returns an empty list when given+-- 'nothing' or a singleton list when not given 'nothing'.+--+-- ==== __Examples__+--+-- Basic usage:+--+-- >>> maybeToList (just 7)+-- [7]+--+-- >>> maybeToList nothing+-- []+--+-- One can use 'maybeToList' to avoid pattern matching when combined+-- with a function that (safely) works on lists:+--+-- >>> import Text.Read ( readMaybe )+-- >>> let parse = fromBaseMaybe . readMaybe :: String -> Maybe Int+-- >>> sum $ maybeToList (parse "3")+-- 3+-- >>> sum $ maybeToList (parse "")+-- 0+--+-- This being said 'Maybe' is an instance of the 'Foldable' typeclass+-- so the example above could also be written as:+--+-- >>> import Text.Read ( readMaybe )+-- >>> let parse = fromBaseMaybe . readMaybe :: String -> Maybe Int+-- >>> sum $ parse "3"+-- 3+-- >>> sum $ parse ""+-- 0+--+maybeToList :: Maybe a -> [a]+maybeToList = maybe [] (: [])+{-# INLINE maybeToList #-}++-- | The 'listToMaybe' function returns 'Nothing' on an empty list+-- or @'Just' a@ where @a@ is the first element of the list.+--+-- ==== __Examples__+--+-- Basic usage:+--+-- >>> listToMaybe []+-- Nothing+--+-- >>> listToMaybe [9]+-- Just 9+--+-- >>> listToMaybe [1,2,3]+-- Just 1+--+-- Composing 'maybeToList' with 'listToMaybe' should be the identity+-- on singleton/empty lists:+--+-- >>> maybeToList $ listToMaybe [5]+-- [5]+-- >>> maybeToList $ listToMaybe []+-- []+--+-- But not on lists with more than one element:+--+-- >>> maybeToList $ listToMaybe [1,2,3]+-- [1]+--+listToMaybe :: [a] -> Maybe a+listToMaybe []    = nothing+listToMaybe (x:_) = just x++-- | The 'catMaybes' function takes a list of 'Maybe's and returns+-- a list of all the 'just' values.+--+-- ==== __Examples__+--+-- Basic usage:+--+-- >>> catMaybes [just 1, nothing, just 3]+-- [1,3]+--+-- When constructing a list of 'Maybe' values, 'catMaybes' can be used+-- to return all of the \"success\" results (if the list is the result+-- of a 'map', then 'mapMaybe' would be more appropriate):+--+-- >>> import Text.Read ( readMaybe )+-- >>> let parse = fromBaseMaybe . readMaybe :: String -> Maybe Int+-- >>> [ parse x | x <- ["1", "Foo", "3"] ]+-- [Just 1,Nothing,Just 3]+-- >>> catMaybes $ [ parse x | x <- ["1", "Foo", "3"] ]+-- [1,3]+--+catMaybes :: [Maybe a] -> [a]+catMaybes = mapMaybe id+{-# INLINE catMaybes #-}++-- | The 'mapMaybe' function is a version of 'map' which can throw+-- out elements.  In particular, the functional argument returns+-- something of type @'Maybe' b@.  If this is 'Nothing', no element+-- is added on to the result list.  If it is @'Just' b@, then @b@ is+-- included in the result list.+--+-- ==== __Examples__+--+-- Using @'mapMaybe' f x@ is a shortcut for @'catMaybes' $ 'map' f x@+-- in most cases:+--+-- >>> import Text.Read ( readMaybe )+-- >>> let parse = fromBaseMaybe . readMaybe :: String -> Maybe Int+-- >>> mapMaybe parse ["1", "Foo", "3"]+-- [1,3]+-- >>> catMaybes $ map parse ["1", "Foo", "3"]+-- [1,3]+--+-- If we map the 'just' function, the entire list should be returned:+--+-- >>> mapMaybe just [1,2,3]+-- [1,2,3]+--+mapMaybe :: (a -> Maybe b) -> [a] -> [b]+mapMaybe _ [] = []+mapMaybe f !(a:as) = let bs = mapMaybe f as in maybe bs (: bs) (f a)+{-# NOINLINE [1] mapMaybe #-}++{-# RULES+"mapMaybe"     [~1] forall f xs. mapMaybe f xs+                    = build (\c n -> foldr (mapMaybeFB c f) n xs)+"mapMaybeList" [1]  forall f. foldr (mapMaybeFB (:) f) [] = mapMaybe f+  #-}++{-# NOINLINE [0] mapMaybeFB #-}+mapMaybeFB :: (b -> r -> r) -> (a -> Maybe b) -> a -> r -> r+mapMaybeFB cons f x next = maybe next (flip cons next) (f x)++-- | The 'fromBaseMaybe' function converts base's 'Data.Maybe.Maybe' to a+--   'Data.Maybe.Unpacked.Maybe'. This function is good for using existing+-- functions that return 'Data.Maybe' maybes.+--+-- ====  __Examples__+--+-- Basic usage:+--+-- >>> import Text.Read ( readMaybe )+-- >>> let parse = fromBaseMaybe . readMaybe :: String -> Maybe Int+-- >>> parse "3"+-- Just 3+-- >>> parse ""+-- Nothing+--+fromBaseMaybe :: BaseMaybe.Maybe a -> Maybe a+fromBaseMaybe (BaseMaybe.Just x) = just x+fromBaseMaybe _                  = nothing+{-# INLINE fromBaseMaybe #-}++-- | The 'toBaseMaybe' function converts a 'Maybe' value to a+--   value of base's 'Data.Maybe.Maybe' type.+--+--   This function is provided for testing and convenience+--   but it is not an idiomatic use of this library. It ruins the speed and space gains from+-- unpacking the 'Maybe'. I implore you to destruct the 'Maybe' with 'maybe' instead.+--+-- ==== __Examples__+--+-- Basic usage:+--+-- >>> import Data.List (unfoldr)+-- >>> let ana n = if n == 5 then nothing else just (n+1,n+1)+-- >>> unfoldr (toBaseMaybe . ana) 0+-- [1,2,3,4,5]+--+toBaseMaybe :: Maybe a -> BaseMaybe.Maybe a+toBaseMaybe = maybe BaseMaybe.Nothing BaseMaybe.Just+{-# INLINE toBaseMaybe #-}++--------------------------------------------------------------------------------++-- Below here lie only instances, and helpers for instances++maybeDataType :: DataType+maybeDataType = mkDataType "Data.Maybe.Unpacked.Maybe" [nothingConstr, justConstr]++nothingConstr :: Constr+nothingConstr = mkConstr maybeDataType "Nothing" [] Prefix++justConstr :: Constr+justConstr = mkConstr maybeDataType "Just" [] Prefix++instance Data a => Data (Maybe a) where+  toConstr = maybe nothingConstr (const justConstr)+  gunfold _ _ = errorWithoutStackTrace "Data.Data.gunfold(Data.Maybe.Unpacked.Maybe)"+  dataTypeOf _ = maybeDataType++instance Functor Maybe where+  fmap f = maybe nothing (just . f)+  {-# INLINE fmap #-}++instance Applicative Maybe where+  pure = just+  {-# INLINE pure #-}+  mf <*> mx = maybe nothing (\f -> fmap f mx) mf+  {-# INLINE (<*>) #-}++instance Monad Maybe where+  return = just+  {-# INLINE return #-}+  mx >>= f = maybe nothing f mx+  {-# INLINE (>>=) #-}++instance MonadFail Maybe where+  fail _ = nothing+  {-# INLINE fail #-}++instance MonadFix Maybe where+  mfix f = let a = f (fromJust a) in a+  {-# INLINE mfix #-}++instance MonadZip Maybe where+  mzipWith = liftA2+  {-# INLINE mzipWith #-}++instance Alternative Maybe where+  empty = nothing+  {-# INLINE empty #-}+  mx <|> my = maybe my just mx+  {-# INLINE (<|>) #-}++instance MonadPlus Maybe where+  mzero = nothing+  {-# INLINE mzero #-}+  mplus mx my = maybe my just mx+  {-# INLINE mplus #-}++instance Foldable Maybe where+  foldMap f ma = maybe mempty f ma+  {-# INLINE foldMap #-}+  foldr f z ma = maybe z ((flip f) z) ma +  {-# INLINE foldr #-}+  foldl f z ma = maybe z (f z) ma+  {-# INLINE foldl #-} +  length  = maybe 0 (const 1)+  {-# INLINE length #-}+  null    = isNothing+  {-# INLINE null #-}+  product = maybe 0 id+  {-# INLINE product #-}+  sum     = maybe 0 id+  {-# INLINE sum #-}++instance Traversable Maybe where+  sequenceA ma = maybe (pure nothing) (fmap just) ma+  {-# INLINE sequenceA #-}+  traverse f ma = maybe (pure nothing) (fmap just . f) ma+  {-# INLINE traverse #-}++instance Semigroup a => Semigroup (Maybe a) where+  ma <> mb = maybe mb (\a -> maybe ma (\b -> just (a <> b)) mb) ma+  {-# INLINE (<>) #-}++instance Semigroup a => Monoid (Maybe a) where+  mempty = nothing+  {-# INLINE mempty #-}+  mappend = (<>)+  {-# INLINE mappend #-}++instance Eq a => Eq (Maybe a) where+  ma == mb = maybe (isNothing mb)+                   (\a -> maybe False (\b -> a == b) mb) ma+  {-# INLINE (==) #-}++instance Ord a => Ord (Maybe a) where+  compare ma mb = maybe LT (\a -> maybe GT (compare a) mb) ma+  {-# INLINE compare #-}++appPrec :: Int+appPrec = 10+{-# INLINE appPrec #-}++instance Show a => Show (Maybe a) where+  showsPrec p ma = maybe (showString "Nothing")+                         (\a -> showParen (p > appPrec) (showString "Just " . (showsPrec (appPrec + 1) a))) ma++instance Read a => Read (Maybe a) where+  readPrec = parens $ nothingP +++ justP+    where nothingP = prec appPrec $ do+            Ident "Nothing" <- lexP+            return nothing+          justP = prec appPrec $ do+            Ident "Just" <- lexP+            a <- step readPrec+            return (just a)++instance Eq1 Maybe where+    liftEq _  Nothing  Nothing  = True+    liftEq _  Nothing  (Just _) = False+    liftEq _  (Just _) Nothing  = False+    liftEq eq (Just x) (Just y) = eq x y++instance Ord1 Maybe where+    liftCompare _    Nothing  Nothing  = EQ+    liftCompare _    Nothing  (Just _) = LT+    liftCompare _    (Just _) Nothing  = GT+    liftCompare comp (Just x) (Just y) = comp x y++instance Read1 Maybe where+    liftReadPrec rp _ =+        parens (expectP (Ident "Nothing") *> pure nothing)+        <|>+        readData (readUnaryWith rp "Just" just)++    liftReadListPrec = liftReadListPrecDefault+    liftReadList     = liftReadListDefault++instance Show1 Maybe where+    liftShowsPrec _  _ _ Nothing  = showString "Nothing"+    liftShowsPrec sp _ d (Just x) = showsUnaryWith sp "Just" d x+
+ test/Main.hs view
@@ -0,0 +1,74 @@+{-# LANGUAGE KindSignatures #-}++module Main (main) where++import Prelude hiding (Maybe(..), maybe)++import Control.Applicative+import Control.Monad (liftM, MonadPlus)+import Control.Monad.Zip (MonadZip)+import Data.Functor.Classes+import Data.Maybe.Unpacked (Maybe(Just, Nothing), nothing, just)+import Data.Monoid (Monoid(mempty,mappend))+import Data.Proxy (Proxy(..))+import Data.Semigroup (Semigroup((<>)))+import Test.QuickCheck.Classes+import Test.QuickCheck.Arbitrary+import Test.QuickCheck.Gen++main :: IO ()+main = lawsCheckMany myClassTests++myClassTests :: [(String, [Laws])]+myClassTests =+  [ ("Ground types", myLaws maybeInt)+  , ("Higher-kinded types", myLaws1 maybeProxy)+  ]++myLaws+  :: (Arbitrary a, Monoid a, Eq a, Ord a, Semigroup a, Show a, Read a)+  => Proxy a -> [Laws]+myLaws p =+  [ commutativeMonoidLaws p+  , eqLaws p+  , ordLaws p+  , semigroupLaws p+  , showReadLaws p+  ]++myLaws1+  :: (Arbitrary1 a, Alternative a, Applicative a, Foldable a, Functor a, Monad a, MonadPlus a, MonadZip a, Traversable a, Eq1 a, Show1 a)  +  => Proxy a -> [Laws]+myLaws1 p =+  [ alternativeLaws p+  , applicativeLaws p+  , foldableLaws p+  , functorLaws p+  , monadLaws p+  , monadPlusLaws p+  , monadZipLaws p+  , traversableLaws p+  ]++maybeProxy :: Proxy Maybe+maybeProxy = Proxy++maybeInt :: Proxy (Maybe Int)+maybeInt = Proxy++instance Semigroup Int where+  (<>) = (+)++instance Monoid Int where+  mempty = 0+  mappend = (+)++instance Arbitrary a => Arbitrary (Maybe a) where+  arbitrary = arbitrary1+  shrink    = shrink1++instance Arbitrary1 Maybe where+  liftArbitrary arb = frequency [(1, return nothing), (3, liftM just arb)]++  liftShrink shr (Just x) = nothing : [ just x' | x' <- shr x ]+  liftShrink _   Nothing  = []
+ unpacked-maybe.cabal view
@@ -0,0 +1,54 @@+--------------------------------------------------------------------------------++name:                unpacked-maybe+version:             0.1.0.0+synopsis:            An unpacked maybe data type+description:+  This module is intended to be a drop-in replacement for the Maybe type provided by base. To shave off pointer chasing, it uses '-XUnboxedSums' to represent the Maybe type as two machine words that are contiguous in memory, without loss of expressiveness that Maybe provides.+  .+  This library provides pattern synonyms Just and Nothing that allow users to pattern match on an Unpacked Maybe in the familiar way.+  .+  Functions are also provided for converting an Unpacked Maybe to the base library's Maybe, and vice versa.+  .+  This library is in alpha, and the internals are likely to change.+homepage:            https://github.com/mckeankylej/unpacked-maybe#readme+license:             BSD3+license-file:        LICENSE+author:              Kyle McKean, chessai+maintainer:          mckean.kylej@gmail.com+copyright:           +  Copyright © 2018 Kyle McKean +  Copyright © 2018chessai+category:            Development+build-type:          Simple+cabal-version:       >=1.10++--------------------------------------------------------------------------------++library+  hs-source-dirs:      src+  exposed-modules:     Data.Maybe.Unpacked+  build-depends:       base >= 4.10 && < 5+                     , ghc-prim+  default-language:    Haskell2010++-------------------------------------------------------------------------------++test-suite unpacked-maybe-test+  type:                exitcode-stdio-1.0+  hs-source-dirs:      test+  main-is:             Main.hs+  build-depends:       base+                     , unpacked-maybe+                     , QuickCheck+                     , quickcheck-classes+  ghc-options:         -threaded -rtsopts -with-rtsopts=-N -O2+  default-language:    Haskell2010++-------------------------------------------------------------------------------++source-repository head+  type:     git+  location: https://github.com/mckeankylej/unpacked-maybe++--------------------------------------------------------------------------------