Boolean 0.0.1 → 0.1.0
raw patch · 4 files changed
+95/−44 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Data.Boolean: instance (IfB bool p, IfB bool q) => IfB bool (p, q)
- Data.Boolean: instance (IfB bool p, IfB bool q, IfB bool r) => IfB bool (p, q, r)
- Data.Boolean: instance (IfB bool p, IfB bool q, IfB bool r, IfB bool s) => IfB bool (p, q, r, s)
- Data.Boolean: instance EqB Bool Float
- Data.Boolean: instance EqB bool a => EqB (z -> bool) (z -> a)
- Data.Boolean: instance IfB Bool Float
- Data.Boolean: instance IfB bool a => IfB (z -> bool) (z -> a)
- Data.Boolean: instance OrdB Bool Float
- Data.Boolean: instance OrdB bool a => OrdB (z -> bool) (z -> a)
+ Data.Boolean: instance (Boolean (BooleanOf a), BooleanOf a ~ Bool) => IfB [a]
+ Data.Boolean: instance (bool ~ BooleanOf p, bool ~ BooleanOf q, IfB p, IfB q) => IfB (p, q)
+ Data.Boolean: instance (bool ~ BooleanOf p, bool ~ BooleanOf q, bool ~ BooleanOf r, IfB p, IfB q, IfB r) => IfB (p, q, r)
+ Data.Boolean: instance (bool ~ BooleanOf p, bool ~ BooleanOf q, bool ~ BooleanOf r, bool ~ BooleanOf s, IfB p, IfB q, IfB r, IfB s) => IfB (p, q, r, s)
+ Data.Boolean: instance EqB Bool
+ Data.Boolean: instance EqB Char
+ Data.Boolean: instance EqB Double
+ Data.Boolean: instance EqB Float
+ Data.Boolean: instance EqB Int
+ Data.Boolean: instance EqB Integer
+ Data.Boolean: instance EqB a => EqB (z -> a)
+ Data.Boolean: instance IfB Bool
+ Data.Boolean: instance IfB Char
+ Data.Boolean: instance IfB Double
+ Data.Boolean: instance IfB Float
+ Data.Boolean: instance IfB Int
+ Data.Boolean: instance IfB Integer
+ Data.Boolean: instance IfB a => IfB (z -> a)
+ Data.Boolean: instance OrdB Bool
+ Data.Boolean: instance OrdB Char
+ Data.Boolean: instance OrdB Double
+ Data.Boolean: instance OrdB Float
+ Data.Boolean: instance OrdB Int
+ Data.Boolean: instance OrdB Integer
+ Data.Boolean: instance OrdB a => OrdB (z -> a)
+ Data.Boolean: sort2B :: (IfB a, OrdB a) => (a, a) -> (a, a)
- Data.Boolean: (<*, >=*, >*, <=*) :: OrdB bool a => a -> a -> bool
+ Data.Boolean: (<*, >=*, >*, <=*) :: (OrdB a, bool ~ BooleanOf a) => a -> a -> bool
- Data.Boolean: (==*, /=*) :: EqB bool a => a -> a -> bool
+ Data.Boolean: (==*, /=*) :: (EqB a, bool ~ BooleanOf a) => a -> a -> bool
- Data.Boolean: boolean :: IfB bool a => a -> a -> bool -> a
+ Data.Boolean: boolean :: (IfB a, bool ~ BooleanOf a) => a -> a -> bool -> a
- Data.Boolean: class Boolean bool => EqB bool a | a -> bool where u /=* v = notB (u ==* v)
+ Data.Boolean: class Boolean (BooleanOf a) => EqB a where u /=* v = notB (u ==* v)
- Data.Boolean: class Boolean bool => IfB bool a | a -> bool
+ Data.Boolean: class Boolean (BooleanOf a) => IfB a
- Data.Boolean: class Boolean bool => OrdB bool a | a -> bool where u >* v = v <* u u >=* v = notB (u <* v) u <=* v = v >=* u
+ Data.Boolean: class Boolean (BooleanOf a) => OrdB a where u >* v = v <* u u >=* v = notB (u <* v) u <=* v = v >=* u
- Data.Boolean: cond :: (Applicative f, IfB bool a) => f bool -> f a -> f a -> f a
+ Data.Boolean: cond :: (Applicative f, IfB a, bool ~ BooleanOf a) => f bool -> f a -> f a -> f a
- Data.Boolean: crop :: (Applicative f, Monoid (f a), IfB bool a) => f bool -> f a -> f a
+ Data.Boolean: crop :: (Applicative f, Monoid (f a), IfB a, bool ~ BooleanOf a) => f bool -> f a -> f a
- Data.Boolean: ifB :: IfB bool a => bool -> a -> a -> a
+ Data.Boolean: ifB :: (IfB a, bool ~ BooleanOf a) => bool -> a -> a -> a
- Data.Boolean: maxB :: (IfB bool a, OrdB bool a) => a -> a -> a
+ Data.Boolean: maxB :: (IfB a, OrdB a) => a -> a -> a
- Data.Boolean: minB :: (IfB bool a, OrdB bool a) => a -> a -> a
+ Data.Boolean: minB :: (IfB a, OrdB a) => a -> a -> a
Files
- Boolean.cabal +11/−5
- COPYING +1/−1
- Makefile +0/−1
- src/Data/Boolean.hs +83/−37
Boolean.cabal view
@@ -1,20 +1,26 @@ Name: Boolean-Version: 0.0.1-Cabal-Version: >= 1.2+Version: 0.1.0+Cabal-Version: >= 1.6 Synopsis: Generalized booleans Category: Data Description: Some classes for generalized boolean operations.+ Starting with 0.1.0, this package uses type families.+ Up to version 0.0.2, it used MPTCs with functional dependencies.+ My thanks to Andy Gill for suggesting & helping with the change. .- Copyright 2009 Conal Elliott; BSD3 license.+ Copyright 2009-2012 Conal Elliott; BSD3 license. Author: Conal Elliott Maintainer: conal@conal.net-Package-Url: http://code.haskell.org/~conal/code/Boolean-Copyright: (c) 2009 by Conal Elliott+Copyright: (c) 2009-2012 by Conal Elliott License: BSD3 License-File: COPYING Stability: experimental build-type: Simple++source-repository head+ type: git+ location: git://github.com/conal/Boolean.git Library hs-Source-Dirs: src
COPYING view
@@ -1,4 +1,4 @@-Copyright (c) 2009 Conal Elliott+Copyright (c) 2009-2012 Conal Elliott All rights reserved. Redistribution and use in source and binary forms, with or without
− Makefile
@@ -1,1 +0,0 @@-include ../cho-home-cabal-make.inc
src/Data/Boolean.hs view
@@ -1,11 +1,16 @@ {-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FunctionalDependencies , UndecidableInstances, ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies, FlexibleContexts, CPP #-} {-# OPTIONS_GHC -Wall #-}++{-# OPTIONS_GHC -fno-warn-unused-imports #-} -- TEMP+{-# OPTIONS_GHC -fno-warn-unused-binds #-} -- TEMP+ ---------------------------------------------------------------------- -- | -- Module : Data.Boolean--- Copyright : (c) Conal Elliott 2009+-- Copyright : (c) Conal Elliott 2009-2012 -- License : BSD3 -- -- Maintainer : conal@conal.net@@ -14,21 +19,24 @@ -- Some classes for generalized boolean operations. -- -- In this design, for if-then-else, equality and inequality tests, the--- boolean type depends functionally on the value type. This dependency--- allows the boolean type to be inferred in a conditional expression.+-- boolean type depends on the value type. -- -- I also tried using a unary type constructor class. The class doesn't work -- for regular booleans, so generality is lost. Also, we'd probably have -- to wire class constraints in like: @(==*) :: Eq a => f Bool -> f a -> f -- a -> f a@, which disallows situations needing additional constraints, -- e.g., Show.--- +--+-- Starting with 0.1.0, this package uses type families.+-- Up to version 0.0.2, it used MPTCs with functional dependencies.+-- My thanks to Andy Gill for suggesting & helping with the change.+ ---------------------------------------------------------------------- module Data.Boolean (- Boolean(..),IfB(..), boolean, cond, crop- , EqB(..), OrdB(..), minB, maxB+ Boolean(..), BooleanOf, IfB(..), boolean, cond, crop+ , EqB(..), OrdB(..), minB, maxB, sort2B ) where import Data.Monoid (Monoid,mempty)@@ -55,85 +63,121 @@ (&&*) = (&&) (||*) = (||) +-- | 'BooleanOf' computed the boolean analog of a specific type.+type family BooleanOf a+ -- | Types with conditionals-class Boolean bool => IfB bool a | a -> bool where- ifB :: bool -> a -> a -> a+class Boolean (BooleanOf a) => IfB a where+ ifB :: (bool ~ BooleanOf a) => bool -> a -> a -> a -- | Expression-lifted conditional with condition last-boolean :: IfB bool a => a -> a -> bool -> a+boolean :: (IfB a, bool ~ BooleanOf a) => a -> a -> bool -> a boolean t e bool = ifB bool t e -- | Point-wise conditional-cond :: (Applicative f, IfB bool a) => f bool -> f a -> f a -> f a+cond :: (Applicative f, IfB a, bool ~ BooleanOf a) => f bool -> f a -> f a -> f a cond = liftA3 ifB --- | Crop a function, filling in 'mempty' where the test yeis false.-crop :: (Applicative f, Monoid (f a), IfB bool a) => f bool -> f a -> f a+-- | Generalized cropping, filling in 'mempty' where the test yields false.+crop :: (Applicative f, Monoid (f a), IfB a, bool ~ BooleanOf a) => f bool -> f a -> f a crop r f = cond r f mempty - infix 4 ==*, /=* -- | Types with equality. Minimum definition: '(==*)'.-class Boolean bool => EqB bool a | a -> bool where- (==*), (/=*) :: a -> a -> bool+class Boolean (BooleanOf a) => EqB a where+ (==*), (/=*) :: (bool ~ BooleanOf a) => a -> a -> bool u /=* v = notB (u ==* v) infix 4 <*, <=*, >=*, >* -- | Types with inequality. Minimum definition: '(<*)'.-class Boolean bool => OrdB bool a | a -> bool where- (<*), (<=*), (>*), (>=*) :: a -> a -> bool+class Boolean (BooleanOf a) => OrdB a where+ (<*), (<=*), (>*), (>=*) :: (bool ~ BooleanOf a) => a -> a -> bool u >* v = v <* u u >=* v = notB (u <* v) u <=* v = v >=* u -- | Variant of 'min' using 'ifB' and '(<=*)'-minB :: (IfB bool a, OrdB bool a) => a -> a -> a+minB :: (IfB a, OrdB a) => a -> a -> a u `minB` v = ifB (u <=* v) u v -- | Variant of 'max' using 'ifB' and '(>=*)'-maxB :: (IfB bool a, OrdB bool a) => a -> a -> a+maxB :: (IfB a, OrdB a) => a -> a -> a u `maxB` v = ifB (u >=* v) u v +-- | Variant of 'min' using 'ifB' and '(<=*)'+sort2B :: (IfB a, OrdB a) => (a,a) -> (a,a)+sort2B (u,v) = ifB (u <=* v) (u,v) (v,u)+ {--------------------------------------------------------------------- Some instances+ Instances for Prelude types --------------------------------------------------------------------} +-- Simple if-then-else as function. ife :: Bool -> a -> a -> a ife c t e = if c then t else e -- I'd give the following instances: -- --- instance IfB Bool a where ifB = ife--- instance EqB Bool a where { (==*) = (==) ; (/=*) = (/=) }--- instance OrdB Bool a where { (<*) = (<) ; (<=*) = (<=)}+-- instance IfB a where ifB = ife+-- instance Eq a => EqB a where { (==*) = (==) ; (/=*) = (/=) }+-- instance Ord a => Ord a where { (<*) = (<) ; (<=*) = (<=)} -- -- Sadly, doing so would break the a->bool fundep, which is needed elsewhere -- for disambiguation. So use the instances above as templates, filling -- in specific types for a. +#define SimpleInstances(Ty) \+instance IfB (Ty) where { ifB = ife } ;\+instance EqB (Ty) where { (==*) = (==) ; (/=*) = (/=) } ;\+instance OrdB (Ty) where { (<*) = (<) ; (<=*) = (<=) } -instance IfB Bool Float where ifB = ife-instance EqB Bool Float where { (==*) = (==) ; (/=*) = (/=) }-instance OrdB Bool Float where { (<*) = (<) ; (<=*) = (<=) }+#define SimpleTy(Ty) \+type instance BooleanOf (Ty) = Bool ;\+SimpleInstances(Ty) --- Similarly for other types. +SimpleTy(Int)+SimpleTy(Integer)+SimpleTy(Float)+SimpleTy(Double)+SimpleTy(Bool)+SimpleTy(Char) +-- Similarly for other simple types. -instance (IfB bool p, IfB bool q) => IfB bool (p,q) where+-- TODO: Export these macros for external use. I guess I'd want a .h file as in+-- the applicative-numbers package.++type instance BooleanOf [a] = BooleanOf a+type instance BooleanOf (a,b) = BooleanOf a+type instance BooleanOf (a,b,c) = BooleanOf a+type instance BooleanOf (a,b,c,d) = BooleanOf a+type instance BooleanOf (z -> a) = z -> BooleanOf a++-- I'm uncomfortable with this list instance. It's unlike tuples and unlike+-- functions. It could be generalized from BooleanOf a ~ Bool to a general case+-- for applicatives, but then the list version would form cross products.+-- Consider strings and other list types under a variety of use scenarios.++instance (Boolean (BooleanOf a),BooleanOf a ~ Bool) => IfB [a] where { ifB = ife }++instance (bool ~ BooleanOf p, bool ~ BooleanOf q+ ,IfB p, IfB q) => IfB (p,q) where ifB w (p,q) (p',q') = (ifB w p p', ifB w q q') -instance (IfB bool p, IfB bool q, IfB bool r) => IfB bool (p,q,r) where+instance (bool ~ BooleanOf p, bool ~ BooleanOf q, bool ~ BooleanOf r+ ,IfB p, IfB q, IfB r)+ => IfB (p,q,r) where ifB w (p,q,r) (p',q',r') = (ifB w p p', ifB w q q', ifB w r r') -instance (IfB bool p, IfB bool q, IfB bool r, IfB bool s) => IfB bool (p,q,r,s) where+instance (bool ~ BooleanOf p, bool ~ BooleanOf q, bool ~ BooleanOf r, bool ~ BooleanOf s+ ,IfB p, IfB q, IfB r, IfB s) => IfB (p,q,r,s) where ifB w (p,q,r,s) (p',q',r',s') = (ifB w p p', ifB w q q', ifB w r r', ifB w s s') ----- Standard pattern for applicative functors:+-- Instances for functions, using the standard pattern for applicative functions.+-- Note that the [] applicative does not use this instance. Fishy. instance Boolean bool => Boolean (z -> bool) where true = pure true@@ -142,14 +186,16 @@ (&&*) = liftA2 (&&*) (||*) = liftA2 (||*) -instance IfB bool a => IfB (z -> bool) (z -> a) where+instance IfB a => IfB (z -> a) where ifB = cond -instance EqB bool a => EqB (z -> bool) (z -> a) where+instance EqB a => EqB (z -> a) where { (==*) = liftA2 (==*) ; (/=*) = liftA2 (/=*) }-instance OrdB bool a => OrdB (z -> bool) (z -> a) where- { (<*) = liftA2(<*) ; (<=*) = liftA2(<=*) }+instance OrdB a => OrdB (z -> a) where+ { (<*) = liftA2 (<*) ; (<=*) = liftA2 (<=*) } +-- TODO: Generalize the function instance into a macro for arbitrary+-- applicatives. Instantiate for functions. {-