boolean-like (empty) → 0.1.0.0
raw patch · 4 files changed
+452/−0 lines, 4 filesdep +attoparsecdep +basedep +bytestringsetup-changed
Dependencies added: attoparsec, base, bytestring, containers, semigroups, text, vector
Files
- Combinator/Booly.hs +388/−0
- LICENSE +30/−0
- Setup.hs +2/−0
- boolean-like.cabal +32/−0
+ Combinator/Booly.hs view
@@ -0,0 +1,388 @@++{-# LANGUAGE ConstraintKinds, DefaultSignatures, GADTs #-}+++-- | A set of typeclasses 'Falsifier', 'Andlike', 'Orlike', and 'Xorlike',+-- that define operations dealing with boolean-representable structures such+-- as 'Maybe' which has true-like 'Just' and false-like 'Nothing', or '[]' by+-- true-like non-empty list and false-like empty list.+module Combinator.Booly+ ( Andlike(..)+ , Orlike(..)+ , Xorlike(..)+ , Falsifier(..)+ , (>&>)+ , (>|>)+ , andLast+ , andHead+ , andMappend+ , andMconcat+ , isFalse+ , isTrue+ , boolF+ , voidF+ , whenF+ , unlessF+ )+ where+++import Control.Applicative (Alternative(..))++-- FIXME both strict and lazy structures when necessary+import qualified Data.Attoparsec.Internal.Types as Atto+import qualified Data.ByteString as BS+import qualified Data.ByteString.Lazy as BL+import qualified Data.Map as Map+import Data.Semigroup (Semigroup(..), Option(..))+import qualified Data.Text as T+import qualified Data.Vector as Vec+++infixr 7 >&>+infixl 7 <&<+infixr 5 >|>+infixl 5 <|<+infixl 6 <^>+++-- | Boolean-like logic operation '>&>' that acts like AND for any+-- boolean-representable datatypes, e.g. '[]' or 'Maybe'.+--+-- __Associativity__+--+-- prop> (a >&> b) >&> c == a >&> (b >&> c)+--+-- __Absorbing element / truth table__+--+-- prop> false >&> false == false+-- prop> false >&> b == false+-- prop> a >&> false == false+-- prop> a >&> b == b+--+class Andlike a where+ -- | Andlike operator, returns the rightmost argument on success, i.e.+ -- if no 'false' are present.+ (<&<) :: a -> a -> a++ -- | '<*' often shares behaviour with '<&<'.+ default (<&<) :: (Applicative f, f b ~ a) => a -> a -> a+ (<&<) = (<*)++-- | Boolean-like logic operation '<|<' that acts like OR for any+-- boolean-representable datatypes, e.g. '[]' or 'Maybe'. It is basically+-- 'Control.Applicative.(<|>)' with a list instance that doesn't append.+--+-- __Associativity__+--+-- prop> (a <|< b) <|< c == a <|< (b <|< c)+--+-- __Absorbing element / truth table__+--+-- prop> false <|< false == false+-- prop> false <|< b == b+-- prop> a <|< false == a+-- prop> a <|< b == a+--+class Orlike a where+ -- | Orlike operator, returns the leftmost true-like argument,+ -- otherwise the rightmost true-like argument, or finally 'false'.+ (<|<) :: a -> a -> a++ -- | All '<|>' instances except list-likes should share behaviour.+ default (<|<) :: (Alternative f, f b ~ a) => a -> a -> a+ (<|<) = (<|>)++-- | Boolean-like logic operation '<^>' that acts like XOR for any+-- boolean-representable datatypes, e.g. '[]' or 'Maybe'.+--+-- __Absorbing element / truth table__+--+-- prop> false <^> false == false+-- prop> false <^> b == b+-- prop> a <^> false == a+-- prop> a <^> b == false+--+class Xorlike a where+ -- | Xorlike operator, returns whichever argument is true-like as both+ -- cannot simultaneously be true-like values, or 'false'.+ (<^>) :: a -> a -> a++class Falsifier a where+ false :: a++ default false :: Monoid a => a+ false = mempty++-- {{{ Instances++instance Andlike () where+ _ <&< _ = ()++instance Orlike () where+ _ <|< _ = ()++instance Xorlike () where+ _ <^> _ = ()++instance Falsifier ()+++instance Andlike Bool where+ (<&<) = (&&)++instance Orlike Bool where+ (<|<) = (||)++instance Xorlike Bool where+ ba <^> bb = (ba || bb) && (not ba || not bb)++instance Falsifier Bool where+ false = False+++instance Andlike (Maybe a) where+ Nothing <&< _ = Nothing+ _ <&< Nothing = Nothing+ a <&< _ = a++instance Orlike (Maybe a) where+ (Just a) <|< _ = Just a+ _ <|< (Just a) = Just a+ _ <|< _ = Nothing++instance Xorlike (Maybe a) where+ (Just a) <^> Nothing = Just a+ Nothing <^> (Just a) = Just a+ _ <^> _ = Nothing++instance Falsifier (Maybe a) where+ false = Nothing+++instance Andlike (Option a) where+ (Option Nothing) <&< _ = Option Nothing+ _ <&< (Option Nothing) = Option Nothing+ a <&< _ = a++instance Orlike (Option a) where+ (Option (Just a)) <|< _ = Option (Just a)+ _ <|< (Option (Just a)) = Option (Just a)+ _ <|< _ = Option Nothing++instance Xorlike (Option a) where+ (Option (Just a)) <^> (Option Nothing) = Option (Just a)+ (Option Nothing) <^> (Option (Just a)) = Option (Just a)+ _ <^> _ = Option Nothing++instance Falsifier (Option a) where+ false = Option Nothing+++instance Andlike (Either a b) where+ (Left a) <&< _ = Left a+ _ <&< (Left b) = Left b+ a <&< _ = a++instance Orlike (Either a b) where+ (Right a) <|< _ = Right a+ _ <|< (Right b) = Right b+ (Left a) <|< _ = Left a+++instance Andlike ([] a) where+ [] <&< _ = []+ _ <&< [] = []+ a <&< _ = a++instance Orlike ([] a) where+ xs@(_:_) <|< _ = xs+ _ <|< xs@(_:_) = xs+ _ <|< _ = []++instance Xorlike ([] a) where+ xs@(_:_) <^> [] = xs+ [] <^> xs@(_:_) = xs+ _ <^> _ = []++instance Falsifier ([] a)+++instance Andlike T.Text where+ ta <&< tb+ | T.null ta || T.null tb = T.empty+ | otherwise = ta++instance Orlike T.Text where+ ta <|< tb+ | not (T.null ta) = ta+ | not (T.null tb) = tb+ | otherwise = T.empty++instance Xorlike T.Text where+ ta <^> tb+ | not (T.null ta) && T.null tb = ta+ | T.null ta && not (T.null tb) = tb+ | otherwise = T.empty++instance Falsifier T.Text+++instance Andlike BS.ByteString where+ ba <&< bb+ | BS.null ba || BS.null bb = BS.empty+ | otherwise = ba+instance Andlike BL.ByteString where+ ba <&< bb+ | BL.null ba || BL.null bb = BL.empty+ | otherwise = ba++instance Orlike BS.ByteString where+ ta <|< tb+ | not (BS.null ta) = ta+ | not (BS.null tb) = tb+ | otherwise = BS.empty+instance Orlike BL.ByteString where+ ta <|< tb+ | not (BL.null ta) = ta+ | not (BL.null tb) = tb+ | otherwise = BL.empty++instance Xorlike BS.ByteString where+ ta <^> tb+ | not (BS.null ta) && BS.null tb = ta+ | BS.null ta && not (BS.null tb) = tb+ | otherwise = BS.empty+instance Xorlike BL.ByteString where+ ta <^> tb+ | not (BL.null ta) && BL.null tb = ta+ | BL.null ta && not (BL.null tb) = tb+ | otherwise = BL.empty++instance Falsifier BS.ByteString+instance Falsifier BL.ByteString+++instance Ord k => Andlike (Map.Map k v) where+ ma <&< mb+ | Map.null ma || Map.null mb = Map.empty+ | otherwise = ma++instance Ord k => Orlike (Map.Map k v) where+ ma <|< mb+ | not (Map.null ma) = ma+ | not (Map.null mb) = mb+ | otherwise = Map.empty++instance Ord k => Xorlike (Map.Map k v) where+ ma <^> mb+ | not (Map.null ma) && Map.null mb = ma+ | Map.null ma && not (Map.null mb) = mb+ | otherwise = Map.empty++instance Ord k => Falsifier (Map.Map k v) where+ false = Map.empty+++instance Andlike (Vec.Vector a)++instance Orlike (Vec.Vector a)++instance Xorlike (Vec.Vector a) where+ va <^> vb+ | not (Vec.null va) && Vec.null vb = va+ | Vec.null va && not (Vec.null vb) = vb+ | otherwise = Vec.empty++instance Falsifier (Vec.Vector a)+++instance Andlike (Atto.Parser i a)++instance Orlike (Atto.Parser i a)++-- TODO+--instance Xorlike (Atto.Parser i a) where++instance Falsifier (Atto.Parser i a)+++instance (Andlike a, Andlike b) => Andlike (a, b) where+ (a1, b1) <&< (a2, b2) = (a1 <&< a2, b1 <&< b2)++instance (Orlike a, Orlike b) => Orlike (a, b) where+ (a1, b1) <|< (a2, b2) = (a1 <|< a2, b1 <|< b2)++instance (Andlike a, Andlike b, Andlike c) => Andlike (a, b, c) where+ (a1, b1, c1) <&< (a2, b2, c2) = (a1 <&< a2, b1 <&< b2, c1 <&< c2)++instance (Orlike a, Orlike b, Orlike c) => Orlike (a, b, c) where+ (a1, b1, c1) <|< (a2, b2, c2) = (a1 <|< a2, b1 <|< b2, c1 <|< c2)++instance (Andlike a, Andlike b, Andlike c, Andlike d) => Andlike (a, b, c, d) where+ (a1, b1, c1, d1) <&< (a2, b2, c2, d2) = (a1 <&< a2, b1 <&< b2, c1 <&< c2, d1 <&< d2)++instance (Orlike a, Orlike b, Orlike c, Orlike d) => Orlike (a, b, c, d) where+ (a1, b1, c1, d1) <|< (a2, b2, c2, d2) = (a1 <|< a2, b1 <|< b2, c1 <|< c2, d1 <|< d2)+++-- }}}+++-- | Flipped version of '<&<'. Returns the leftmost argument on both+-- success or failure.+(>&>) :: Andlike a => a -> a -> a+(>&>) = flip (<&<)++-- | Flipped version of '<|<'. Returns the leftmost argument on both+-- success or failure.+(>|>) :: Orlike a => a -> a -> a+(>|>) = flip (<|<)++-- | Returns the first element on success of all values.+andHead :: (Andlike a, Falsifier a, Foldable t) => t a -> a+andHead as+ | null as = false+ | otherwise = foldr1 (<&<) as++-- | Returns the last element on success of all values.+andLast :: (Andlike a, Falsifier a, Foldable t) => t a -> a+andLast as+ | null as = false+ | otherwise = foldr1 (>&>) as++-- | Monadic append with the annihilating operator guarding each argument.+-- Returns the mappended result on success.+andMappend :: (Andlike a, Monoid a) => a -> a -> a+andMappend a b = (a <&< b) `mappend` (a >&> b)++-- | Monadic concatenation with the annihilating operator guarding each argument.+andMconcat :: (Andlike a, Falsifier a, Monoid a, Foldable t) => t a -> a+andMconcat as+ | null as = false+ | otherwise = foldr1 andMappend as++isFalse :: (Eq a, Falsifier a) => a -> Bool+isFalse = (false ==)++isTrue :: (Eq a, Falsifier a) => a -> Bool+isTrue = not . isFalse++-- | Similar to 'Data.Bool.bool'.+boolF :: (Eq b, Falsifier b) => a -> a -> b -> a+boolF a b f = if isTrue f then a else b++-- | Discard the argument and return 'false'.+voidF :: Falsifier a => a -> a+voidF = const false++-- | Similar to `when` but takes a boolean-like and returns `false`+-- instead of `()`.+whenF :: (Eq a, Eq b, Falsifier a, Falsifier b) => a -> b -> b+whenF fa fb = if isTrue fa then fb else false++-- | Similar to `unless` but takes a boolean-like and returns `false`+-- instead of `()`.+unlessF :: (Eq a, Eq b, Falsifier a, Falsifier b) => a -> b -> b+unlessF fa fb = if isFalse fa then fb else false+
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Benedict Aas (c) 2016++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 Author name here 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
+ boolean-like.cabal view
@@ -0,0 +1,32 @@+name: boolean-like+version: 0.1.0.0+synopsis: Logical combinatory operations dealing with datatypes+ representing booleans by their constructors.+description:+ Boolean-like logical combinatory operations under typeclasses+ Andlike, Orlike, and Xorlike and a typeclass Falsifier for datatypes with+ unary false-like values (e.g. Nothing, []).+homepage: http://github.com/Shou/boolean-like+bug-reports: http://github.com/Shou/boolean-like/issues+license: BSD3+license-file: LICENSE+author: Benedict Aas+maintainer: x@shou.io+copyright: 2016 Benedict Aas+category: Control+build-type: Simple+-- extra-source-files:+cabal-version: >=1.10+tested-with:+ GHC==7.10.3++library+ exposed-modules: Combinator.Booly+ build-depends: attoparsec, base >= 4.7 && < 5, bytestring, containers,+ semigroups, text, vector+ default-language: Haskell2010++source-repository head+ type: git+ location: https://github.com/Shou/boolean-like+