reactive-0.5: src/Data/Improving.hs
----------------------------------------------------------------------
-- |
-- Module : Data.Improving
-- Copyright : (c) Conal Elliott 2008
-- License : BSD3
--
-- Maintainer : conal@conal.net
-- Stability : experimental
--
-- Improving values -- efficient version
----------------------------------------------------------------------
module Data.Improving
(
Improving(..), minI
) where
import Data.Unamb (unamb,assuming)
{----------------------------------------------------------
Improving values
----------------------------------------------------------}
-- | An improving value.
data Improving a = IV a (a -> Ordering)
-- | A known improving value (which doesn't really improve)
exactly :: Ord a => a -> Improving a
exactly a = IV a (compare a)
instance Eq a => Eq (Improving a) where
IV a _ == IV b _ = a == b
instance Ord a => Ord (Improving a) where
s `min` t = fst (s `minI` t)
s <= t = snd (s `minI` t)
-- | Efficient combination of 'min' and '(<=)'
minI :: Ord a => Improving a -> Improving a -> (Improving a,Bool)
IV u uComp `minI` IV v vComp = (IV uMinV wComp, uLeqV)
where
uMinV = if uLeqV then u else v
-- u <= v: Try @v `compare` u /= LT@ and @u `compare` v /= GT@.
uLeqV = (vComp u /= LT) `unamb` (uComp v /= GT)
-- (u `min` v) `compare` t: Try comparing according to whether u <= v,
-- or go with either answer if they agree, e.g., if both say GT.
minComp = if uLeqV then uComp else vComp
wComp t = minComp t `unamb`
assuming (uCompT == vCompT) uCompT
where
uCompT = uComp t
vCompT = vComp t