Boolean (empty) → 0.0.0
raw patch · 5 files changed
+220/−0 lines, 5 filesdep +basesetup-changed
Dependencies added: base
Files
- Boolean.cabal +28/−0
- COPYING +25/−0
- Makefile +1/−0
- Setup.lhs +3/−0
- src/Data/Boolean.hs +163/−0
+ Boolean.cabal view
@@ -0,0 +1,28 @@+Name: Boolean+Version: 0.0.0+Cabal-Version: >= 1.2+Synopsis: Generalized boolean ops+Category: Data+Description:+ Some classes for generalized boolean operations.+ .+ Copyright 2009 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+License: BSD3+License-File: COPYING+Stability: experimental+build-type: Simple++Library+ hs-Source-Dirs: src+ Extensions:+ Build-Depends: base<5+ Exposed-Modules:+ Data.Boolean+ + ghc-options: -Wall++-- ghc-prof-options: -prof -auto-all
+ COPYING view
@@ -0,0 +1,25 @@+Copyright (c) 2009 Conal Elliott+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:+1. Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.+2. 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.+3. The names of the authors may not be used to endorse or promote products+ derived from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``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 AUTHORS 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.+
+ Makefile view
@@ -0,0 +1,1 @@+include ../cho-home-cabal-make.inc
+ Setup.lhs view
@@ -0,0 +1,3 @@+#!/usr/bin/env runhaskell+> import Distribution.Simple+> main = defaultMain
+ src/Data/Boolean.hs view
@@ -0,0 +1,163 @@+{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FunctionalDependencies+ , UndecidableInstances, ScopedTypeVariables+ #-}+{-# OPTIONS_GHC -Wall #-}+----------------------------------------------------------------------+-- |+-- Module : Data.Boolean+-- Copyright : (c) Conal Elliott 2009+-- License : BSD3+-- +-- Maintainer : conal@conal.net+-- Stability : experimental+-- +-- 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.+-- +-- 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.+-- +----------------------------------------------------------------------++module Data.Boolean+ (+ Boolean(..),IfB(..), boolean, cond, crop+ , EqB(..), OrdB(..)+ ) where++import Data.Monoid (Monoid,mempty)+import Control.Applicative (Applicative(..),liftA2,liftA3)+++{--------------------------------------------------------------------+ Classes+--------------------------------------------------------------------}++infixr 3 &&*+infixr 2 ||*++-- | Generalized boolean class+class Boolean b where+ true, false :: b+ notB :: b -> b+ (&&*), (||*) :: b -> b -> b++instance Boolean Bool where+ true = True+ false = False+ notB = not+ (&&*) = (&&)+ (||*) = (||)++-- | Types with conditionals+class Boolean bool => IfB bool a | a -> bool where+ ifB :: bool -> a -> a -> a++-- | Expression-lifted conditional with condition last+boolean :: IfB bool 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 = 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+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+ u /=* v = notB (u ==* v)++infix 4 <*, <=*, >=*, >*++-- | Types with inequality. Minimum definition: '(<*)'.+class Boolean bool => OrdB bool a | a -> bool where+ (<*), (<=*), (>*), (>=*) :: a -> a -> bool+ u >* v = v <* u+ u >=* v = notB (u <* v)+ u <=* v = v >=* u++{--------------------------------------------------------------------+ Some instances+--------------------------------------------------------------------}++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 { (<*) = (<) ; (<=*) = (<=)}+-- +-- 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.+++instance IfB Bool Float where ifB = ife+instance EqB Bool Float where { (==*) = (==) ; (/=*) = (/=) }+instance OrdB Bool Float where { (<*) = (<) ; (<=*) = (<=) }++-- Similarly for other types. +++instance (IfB bool p, IfB bool q) => IfB bool (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+ 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+ 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:++instance Boolean bool => Boolean (z -> bool) where+ true = pure true+ false = pure false+ notB = fmap notB+ (&&*) = liftA2 (&&*)+ (||*) = liftA2 (||*)++instance IfB bool a => IfB (z -> bool) (z -> a) where+ ifB = cond++instance EqB bool a => EqB (z -> bool) (z -> a) where+ { (==*) = liftA2 (==*) ; (/=*) = liftA2 (/=*) }+instance OrdB bool a => OrdB (z -> bool) (z -> a) where+ { (<*) = liftA2(<*) ; (<=*) = liftA2(<=*) }+++{-++{--------------------------------------------------------------------+ Tests+--------------------------------------------------------------------}++t1 :: String+t1 = ifB True "foo" "bar"++t2 :: Float -> Float+t2 = ifB (< 0) negate id++-- No instance for (IfB (a -> Bool) (a1 -> a1))+-- arising from a use of `ifB'+-- +-- t2 = ifB (< 0) negate id -- abs++-}