packages feed

optional-args (empty) → 1.0.0

raw patch · 4 files changed

+201/−0 lines, 4 filesdep +basesetup-changed

Dependencies added: base

Files

+ LICENSE view
@@ -0,0 +1,24 @@+Copyright (c) 2015 Gabriel Gonzalez+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 Gabriel Gonzalez 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
+ optional-args.cabal view
@@ -0,0 +1,26 @@+Name: optional-args+Version: 1.0.0+Cabal-Version: >=1.10+Build-Type: Simple+License: BSD3+License-File: LICENSE+Copyright: 2015 Gabriel Gonzalez+Author: Gabriel Gonzalez+Maintainer: Gabriel439@gmail.com+Bug-Reports: https://github.com/Gabriel439/Haskell-Optional-Args-Library/issues+Synopsis: Optional function arguments+Description: This library provides a type for specifying `Optional` function+  arguments+  .+  Read the tutorial in "Data.Optional" to learn more+Category: Data+Source-Repository head+    Type: git+    Location: https://github.com/Gabriel439/Haskell-Optional-Args-Library++Library+    HS-Source-Dirs: src+    Build-Depends: base >= 4.5 && < 5+    Exposed-Modules: Data.Optional+    GHC-Options: -O2 -Wall+    Default-Language: Haskell2010
+ src/Data/Optional.hs view
@@ -0,0 +1,149 @@+{-# LANGUAGE DeriveFunctor     #-}+{-# LANGUAGE DeriveFoldable    #-}+{-# LANGUAGE DeriveTraversable #-}++-- | Use the `Optional` type for optional function arguments.  For example:+-- +-- > import Data.Optional+-- >+-- > greet :: Optional String -> String+-- > greet (Specific name) = "Hello, " ++ name+-- > greet  Default        = "Hello"+-- +-- >>> greet (Specific "John")+-- "Hello, John"+-- >>> greet Default+-- "Hello"+-- +--     The `Optional` type overloads as many Haskell literals as possible so+--     that you do not need to wrap values in `Specific`.  For example, if you+--     enable the `OverloadedStrings` extension you can use a naked string+--     literal instead:+-- +-- >>> :set -XOverloadedStrings+-- >>> greet "John"+-- "Hello, John"+-- +--     The `Optional` type also implements `Num` and `Fractional`, so you can+--     use numeric literals in place of `Optional` values:+-- +-- > birthday :: Optional Int -> String+-- > birthday (Specific age) = "You are " ++ show age ++ " years old!"+-- > birthday  Default       = "You are one year older!"+-- +-- >>> birthday 20+-- "You are 20 years old!"+-- >>> birthday Default+-- "You are one year older!"+-- +--     The `IsString`, `Num`, and `Fractional` instances are recursive, so you+--     can wrap your types in a more descriptive newtype and derive `IsString`,+--     `Num` or `Fractional`:+-- +-- > {-# LANGUAGE GeneralizedNewtypeDeriving #-}+-- > +-- > import Data.Optional+-- > import Data.String (IsString)+-- > +-- > newtype Name = Name { getName :: String } deriving (IsString)+-- > +-- > greet :: Optional Name -> String+-- > greet (Specific name) = "Hello, " ++ getName name+-- > greet  Default        = "Hello"+-- > +-- > newtype Age = Age { getAge :: Int } deriving (Num)+-- > +-- > birthday :: Optional Age -> String+-- > birthday (Specific age) = "You are " ++ show (getAge age) ++ " years old!"+-- > birthday  Default       = "You are one year older!"+-- +--     ... and you would still be able to provide naked numeric or string+--     literals:+-- +-- >>> :set -XOverloadedStrings+-- >>> greet "John"+-- "Hello, John"+-- >>> birthday 20+-- "You are 20 years old!"+-- +--     You can use `empty` as a short-hand for a `Default` argument:+-- +-- >>> greet empty+-- "Hello"+-- >>> birthday empty+-- "You are one year older!"+-- +--     You can also use `pure` as a short-hand for a `Specific` argument:+-- +-- >>> greet (pure "John")+-- "Hello, John"+-- >>> birthday (pure 20)+-- "You are 20 years old!"++module Data.Optional (+    -- * Optional+      Optional(..)++    -- * Re-exports+    , empty+    , pure+    ) where++import Control.Applicative (Applicative(..), Alternative(..), liftA2)+import Control.Monad (MonadPlus(..))+import Data.Foldable (Foldable)+import Data.Traversable (Traversable)+import Data.Monoid (Monoid(..))+import Data.String (IsString(..))++-- | A function argument that has a `Default` value+data Optional a = Default | Specific a+    deriving (Eq, Functor, Foldable, Traversable, Show)++instance Applicative Optional where+    pure = Specific++    Specific f <*> Specific x = Specific (f x)+    _          <*> _          = Default++instance Monad Optional where+    return = Specific++    Default    >>= _ = Default+    Specific x >>= f = f x++instance Alternative Optional where+    empty = Default++    Default <|> x = x+    x       <|> _ = x++instance MonadPlus Optional where+    mzero = empty+    mplus = (<|>)++instance Monoid a => Monoid (Optional a) where+    mempty = pure mempty++    mappend = liftA2 mappend++instance IsString a => IsString (Optional a) where+    fromString str = pure (fromString str)++instance Num a => Num (Optional a) where+    fromInteger n = pure (fromInteger n)++    (+) = liftA2 (+)+    (*) = liftA2 (*)+    (-) = liftA2 (-)++    negate = fmap negate+    abs    = fmap abs+    signum = fmap signum++instance Fractional a => Fractional (Optional a) where+    fromRational n = pure (fromRational n)++    recip = fmap recip++    (/) = liftA2 (/)