{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Perhaps (Prob,
Perhaps(..), never, always, impossible, possible, perhaps) where
-- Probabilities (0.0..1.0)
newtype Prob = P Float
deriving (Eq, Ord, Num, Real, Fractional, RealFrac)
instance Show Prob where
show (P p) = show i ++ "." ++ show f ++ "%"
where
digits = round (1000 * p)
(i, f) = (digits `div` 10, digits `mod` 10)
-- A generalization of Maybe a
data Perhaps a = Perhaps { value :: a, probability :: Prob }
deriving (Show)
never :: Perhaps a
never = Perhaps undefined 0
always :: a -> Perhaps a
always x = Perhaps x 1
impossible :: Perhaps a -> Bool
impossible (Perhaps _ p) = p == 0
possible :: Perhaps a -> Bool
possible = not . impossible
perhaps :: b -> (a -> b) -> Perhaps a -> b
perhaps def _ (Perhaps _ 0) = def
perhaps _ f (Perhaps x _) = f x
instance Monad Perhaps where
return x = always x
(Perhaps _ 0) >>= g = never -- value may be undefined if probability is 0 (cf. never)
(Perhaps x p1) >>= g = Perhaps y (p1 * p2) -- independence assumption
where
Perhaps y p2 = g x