diff --git a/random-fu.cabal b/random-fu.cabal
--- a/random-fu.cabal
+++ b/random-fu.cabal
@@ -1,5 +1,5 @@
 name:                   random-fu
-version:                0.2.1.1
+version:                0.2.2.0
 stability:              provisional
 
 cabal-version:          >= 1.6
@@ -28,6 +28,8 @@
                         comparable to other Haskell libraries, but still
                         a fair bit slower than straight C implementations of 
                         the same algorithms.
+                        .
+                        Changes in 0.2.2.0: Bug fixes in Data.Random.Distribution.Categorical.
                         .
                         Changes in 0.2.1.1: Changed some one-field data types
                         to newtypes, updated types for GHC 7.4's removal of Eq 
diff --git a/src/Data/Random/Distribution/Categorical.hs b/src/Data/Random/Distribution/Categorical.hs
--- a/src/Data/Random/Distribution/Categorical.hs
+++ b/src/Data/Random/Distribution/Categorical.hs
@@ -6,7 +6,8 @@
 module Data.Random.Distribution.Categorical
     ( Categorical
     , categorical, categoricalT
-    , fromList, toList
+    , weightedCategorical, weightedCategoricalT
+    , fromList, toList, totalWeight, numEvents
     , fromWeightedList, fromObservations
     , mapCategoricalPs, normalizeCategoricalPs
     , collectEvents, collectEventsBy
@@ -39,6 +40,16 @@
 categoricalT :: (Num p, Distribution (Categorical p) a) => [(p,a)] -> RVarT m a
 categoricalT = rvarT . fromList
 
+-- |Construct a 'Categorical' random variable from a list of probabilities
+-- and categories, where the probabilities all sum to 1.
+weightedCategorical :: (Fractional p, Eq p, Distribution (Categorical p) a) => [(p,a)] -> RVar a
+weightedCategorical = rvar . fromWeightedList
+
+-- |Construct a 'Categorical' random process from a list of probabilities 
+-- and categories, where the probabilities all sum to 1.
+weightedCategoricalT :: (Fractional p, Eq p, Distribution (Categorical p) a) => [(p,a)] -> RVarT m a
+weightedCategoricalT = rvarT . fromWeightedList
+
 -- | Construct a 'Categorical' distribution from a list of weighted categories.
 {-# INLINE fromList #-}
 fromList :: (Num p) => [(p,a)] -> Categorical p a
@@ -52,6 +63,14 @@
         g x [] = [x]
         g x@(p0,_) ((p1, y):xs) = x : (p1-p0,y) : xs
 
+totalWeight :: Num p => Categorical p a -> p
+totalWeight (Categorical ds)
+    | V.null ds = 0
+    | otherwise = fst (V.last ds)
+
+numEvents :: Categorical p a -> Int
+numEvents (Categorical ds) = V.length ds
+
 -- |Construct a 'Categorical' distribution from a list of weighted categories, 
 -- where the weights do not necessarily sum to 1.
 fromWeightedList :: (Fractional p, Eq p) => [(p,a)] -> Categorical p a
@@ -165,44 +184,45 @@
     (<*>) = ap
 
 -- |Like 'fmap', but for the probabilities of a categorical distribution.
-mapCategoricalPs :: (p -> q) -> Categorical p e -> Categorical q e
-mapCategoricalPs f (Categorical ds) = Categorical (V.map (first f) ds)
+mapCategoricalPs :: (Num p, Num q) => (p -> q) -> Categorical p e -> Categorical q e
+mapCategoricalPs f = fromList . map (first f) . toList
 
 -- |Adjust all the weights of a categorical distribution so that they 
 -- sum to unity and remove all events whose probability is zero.
 normalizeCategoricalPs :: (Fractional p, Eq p) => Categorical p e -> Categorical p e
-normalizeCategoricalPs orig@(Categorical ds) = 
-    if V.null ds
-        then orig
-        else runST $ do
-            let n = V.length ds
-            lastP       <- newSTRef 0
-            nDups       <- newSTRef 0
-            normalized  <- V.thaw ds
-            
-            let skip = modifySTRef' nDups (1+)
-                save i p x = do
-                    d <- readSTRef nDups
-                    MV.write normalized (i-d) (p, x)
-            
-            sequence_
-                [ do
-                    let (p,x) = ds V.! i
-                    p0 <- readSTRef lastP
-                    if p == p0
-                        then skip
-                        else do
-                            save i (p * scale) x
-                            writeSTRef lastP $! p
-                | i <- [0..n-1]
-                ]
-            
-            -- force last element to 1
-            d <- readSTRef nDups
-            MV.write normalized (n-d-1) (1,lastX)
-            Categorical <$> V.unsafeFreeze (MV.unsafeSlice 0 (n-d) normalized)
+normalizeCategoricalPs orig@(Categorical ds)
+    | ps == 0   = Categorical V.empty
+    | otherwise = runST $ do
+        lastP       <- newSTRef 0
+        nDups       <- newSTRef 0
+        normalized  <- V.thaw ds
+        
+        let n           = V.length ds
+            skip        = modifySTRef' nDups (1+)
+            save i p x  = do
+                d <- readSTRef nDups
+                MV.write normalized (i-d) (p, x)
+        
+        sequence_
+            [ do
+                let (p,x) = ds V.! i
+                p0 <- readSTRef lastP
+                if p == p0
+                    then skip
+                    else do
+                        save i (p * scale) x
+                        writeSTRef lastP $! p
+            | i <- [0..n-1]
+            ]
+        
+        -- force last element to 1
+        d <- readSTRef nDups
+        let n' = n-d
+        (_,lastX) <- MV.read normalized (n'-1)
+        MV.write normalized (n'-1) (1,lastX)
+        Categorical <$> V.unsafeFreeze (MV.unsafeSlice 0 n' normalized)
     where
-        (ps, lastX) = V.last ds
+        ps = totalWeight orig
         scale = recip ps
 
 -- |strict 'modifySTRef'
