-- http://forums.xkcd.com/viewtopic.php?f=40&t=66809
-- | Define chained operators, for ease of entering expressions like 1 < 2 < 3.
-- This module defines three extra variations of each of the operators '<',
-- '<=', and '==', for use at the beginning, middle, and end of such chains.
-- These operators have dots on the inside of the chain, for instance:
--
-- >x <. y .< z
-- >1 <. 2 .<. 3 .<=. 3 .< 4
-- >square (0,0) ==. square (0,1) .== square (0,2)
--
-- These operators are defined to be left-associative and the same precedence
-- as the ordinary comparison operators.
module ChainCompare where
chainBegin :: (a -> b -> Bool) -> a -> b -> Maybe b
chainBegin op x y = if x `op` y then Just y else Nothing
chainEnd :: (a -> b -> Bool) -> Maybe a -> b -> Bool
chainEnd op x y = maybe False (`op` y) x
chainMiddle :: (a -> b -> Bool) -> Maybe a -> b -> Maybe b
chainMiddle = chainBegin . chainEnd
infixl 4 <., .<, .<.
(<.) :: Ord a => a -> a -> Maybe a
(<.) = chainBegin (<)
(.<) :: Ord a => Maybe a -> a -> Bool
(.<) = chainEnd (<)
(.<.) :: Ord a => Maybe a -> a -> Maybe a
(.<.) = chainMiddle (<)
infixl 4 <=., .<=, .<=.
(<=.) :: Ord a => a -> a -> Maybe a
(<=.) = chainBegin (<=)
(.<=) :: Ord a => Maybe a -> a -> Bool
(.<=) = chainEnd (<=)
(.<=.) :: Ord a => Maybe a -> a -> Maybe a
(.<=.) = chainMiddle (<=)
infixl 4 ==., .==, .==.
(==.) :: Eq a => a -> a -> Maybe a
(==.) = chainBegin (==)
(.==) :: Eq a => Maybe a -> a -> Bool
(.==) = chainEnd (==)
(.==.) :: Eq a => Maybe a -> a -> Maybe a
(.==.) = chainMiddle (==)