diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,14 +1,22 @@
+# 0.4.0.0
+
+- New functions (blmage)
+
+    + `LiftM`, `LiftM2`, `LiftM3`
+    + `(<=)`, `(>=)`, `(<)`, `(>)`
+    + `Guarded`, `Guard((:=))`, `Otherwise`
+
 # 0.3.0.1
 
 - GHC 8.6 compatibility
 
 # 0.3.0.0
 
-- More new functions, thanks to isovector
+- More new functions, (isovector)
 
 # 0.2.0.0
 
-- A whole bunch of basic functions, thanks to isovector
+- A whole bunch of basic functions (isovector)
 - Remove `Traverse` (now `Map`), `BimapPair`, `BimapEither` (now `Bimap`)
 
 # 0.1.0.0
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,8 +1,45 @@
 # First-class type families [![Hackage](https://img.shields.io/hackage/v/first-class-families.svg)](https://hackage.haskell.org/package/first-class-families) [![Build Status](https://travis-ci.org/Lysxia/first-class-families.svg)](https://travis-ci.org/Lysxia/first-class-families)
 
-[Haskell with only one type family](http://blog.poisson.chat/posts/2018-08-06-one-type-family.html) (blogpost)
+For example, consider this simple type family:
 
-See `src/Fcf`.
+```haskell
+type family   FromMaybe (a :: k) (m :: Maybe k) :: k
+type instance FromMaybe a 'Nothing  = a
+type instance FromMaybe a ('Just b) = b
+```
+
+With first-class-families, it translates to a `data` declaration
+and instances for a single `Eval` family:
+
+```haskell
+import Fcf
+
+data FromMaybe :: k -> Maybe k -> Exp k
+type instance Eval (FromMaybe a 'Nothing)  = a
+type instance Eval (FromMaybe a ('Just b)) = b
+```
+
+That way, the `FromMaybe` constructor can be passed to higher-order fcfs.
+
+```haskell
+Eval (Map (FromMaybe 0) '[ 'Just 1, 'Nothing ])  =  '[ 1, 0 ] :: [Nat]
+```
+
+Essential language extensions:
+
+```haskell
+{-# LANGUAGE
+    DataKinds,
+    PolyKinds,
+    TypeFamilies,
+    TypeInType,
+    TypeOperators,
+    UndecidableInstances #-}
+```
+
+## See also
+
+[Haskell with only one type family](http://blog.poisson.chat/posts/2018-08-06-one-type-family.html) (blogpost)
 
 ---
 
diff --git a/first-class-families.cabal b/first-class-families.cabal
--- a/first-class-families.cabal
+++ b/first-class-families.cabal
@@ -1,5 +1,5 @@
 name:                first-class-families
-version:             0.3.0.1
+version:             0.4.0.0
 synopsis:
   First class type families
 description:
@@ -28,6 +28,15 @@
     base >= 4.9 && < 5
   ghc-options:         -Wall
   default-language:    Haskell2010
+
+test-suite fcf-test
+  type:                exitcode-stdio-1.0
+  hs-source-dirs:      test
+  main-is:             test.hs
+  default-language:    Haskell2010
+  build-depends:
+    base,
+    first-class-families
 
 source-repository head
   type:     git
diff --git a/src/Fcf.hs b/src/Fcf.hs
--- a/src/Fcf.hs
+++ b/src/Fcf.hs
@@ -76,6 +76,14 @@
 data (<=<) :: (b -> Exp c) -> (a -> Exp b) -> a -> Exp c
 type instance Eval ((f <=< g) x) = Eval (f (Eval (g x)))
 
+type LiftM = (=<<)
+
+data LiftM2 :: (a -> b -> Exp c) -> Exp a -> Exp b -> Exp c
+type instance Eval (LiftM2 f x y) = Eval (f (Eval x) (Eval y))
+
+data LiftM3 :: (a -> b -> c -> Exp d) -> Exp a -> Exp b -> Exp c -> Exp d
+type instance Eval (LiftM3 f x y z) = Eval (f (Eval x) (Eval y) (Eval z))
+
 data Join :: Exp (Exp a) -> Exp a
 type instance Eval (Join e) = Eval (Eval e)
 
@@ -294,6 +302,33 @@
 type instance Eval (Not 'True)  = 'False
 type instance Eval (Not 'False) = 'True
 
+-- | A conditional choosing the first branch whose guard @a -> 'Exp' 'Bool'@
+-- accepts a given value @a@.
+--
+-- === Example
+--
+-- @
+-- type UnitPrefix n = 'Eval' ('Guarded' n
+--   '[ 'TyEq' 0 \'':=' 'Pure' \"\"
+--    , 'TyEq' 1 \'':=' 'Pure' \"deci\"
+--    , 'TyEq' 2 \'':=' 'Pure' \"hecto\"
+--    , 'TyEq' 3 \'':=' 'Pure' \"kilo\"
+--    , 'TyEq' 6 \'':=' 'Pure' \"mega\"
+--    , 'TyEq' 9 \'':=' 'Pure' \"giga\"
+--    , 'Otherwise' \'':=' 'Error' "Something else"
+--    ])
+-- @
+data Guarded :: a -> [Guard (a -> Exp Bool) (Exp b)] -> Exp b
+type instance Eval (Guarded x ((p ':= y) ': ys)) =
+    Eval (If (Eval (p x)) y (Guarded x ys))
+
+-- | A fancy-looking pair type to use with 'Guarded'.
+data Guard a b = a := b
+infixr 0 :=
+
+-- | A catch-all guard for 'Guarded'.
+type Otherwise = ConstFn 'True
+
 -- ** Nat
 
 data (+) :: Nat -> Nat -> Exp Nat
@@ -307,6 +342,18 @@
 
 data (^) :: Nat -> Nat -> Exp Nat
 type instance Eval ((^) a b) = a TL.^ b
+
+data (<=) :: Nat -> Nat -> Exp Bool
+type instance Eval ((<=) a b) = a TL.<=? b
+
+data (>=) :: Nat -> Nat -> Exp Bool
+type instance Eval ((>=) a b) = b TL.<=? a
+
+data (<) :: Nat -> Nat -> Exp Bool
+type instance Eval ((<) a b) = Eval (Not =<< (a >= b))
+
+data (>) :: Nat -> Nat -> Exp Bool
+type instance Eval ((>) a b) = Eval (Not =<< (a <= b))
 
 -- ** Other
 
diff --git a/test/test.hs b/test/test.hs
new file mode 100644
--- /dev/null
+++ b/test/test.hs
@@ -0,0 +1,28 @@
+{-# LANGUAGE
+    DataKinds,
+    KindSignatures,
+    TypeOperators #-}
+
+import Data.Type.Equality ((:~:)(Refl))
+import GHC.TypeLits (Nat)
+import Fcf
+
+type UnitPrefix (n :: Nat) = Eval (Guarded n
+  '[ TyEq 0 ':= Pure ""
+   , TyEq 1 ':= Pure "deci"
+   , TyEq 2 ':= Pure "hecto"
+   , TyEq 3 ':= Pure "kilo"
+   , TyEq 6 ':= Pure "mega"
+   , TyEq 9 ':= Pure "giga"
+   , Otherwise ':= Error "Something else"
+   ])
+
+-- Compile-time tests
+
+_ = Refl :: UnitPrefix 0 :~: ""
+_ = Refl :: UnitPrefix 9 :~: "giga"
+
+-- Dummy
+
+main :: IO ()
+main = pure ()
