diff --git a/CHANGELOG b/CHANGELOG
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,8 @@
 # Changelog
 
+- 0.1.1 (2025-02-23)
+  * Haddock improvements and examples.
+
 - 0.1.0 (2025-02-22)
   * Initial release, supporting basic HD wallet functionality.
 
diff --git a/bench/Main.hs b/bench/Main.hs
--- a/bench/Main.hs
+++ b/bench/Main.hs
@@ -29,6 +29,7 @@
       , bench_derive_priv
       , bench_xpub
       , bench_xprv
+      , bench_parse
     ]
   ]
 
diff --git a/lib/Crypto/HDKey/BIP32.hs b/lib/Crypto/HDKey/BIP32.hs
--- a/lib/Crypto/HDKey/BIP32.hs
+++ b/lib/Crypto/HDKey/BIP32.hs
@@ -1,3 +1,4 @@
+{-# OPTIONS_HADDOCK prune #-}
 {-# LANGUAGE BangPatterns #-}
 {-# LANGUAGE BinaryLiterals #-}
 {-# LANGUAGE LambdaCase #-}
@@ -26,6 +27,9 @@
   , XPub(..)
   , XPrv(..)
   , X(..)
+  , ckd_pub
+  , ckd_priv
+  , n
 
   -- * Child derivation via path
   , derive
@@ -96,14 +100,10 @@
       !w1 = fi (w .>>. 16) .&. mask
       !w2 = fi (w .>>. 08) .&. mask
       !w3 = fi w .&. mask
-  in  BS.cons w0 (BS.cons w1 (BS.cons w2 (BS.singleton w3))) -- XX
+  in  BS.cons w0 (BS.cons w1 (BS.cons w2 (BS.singleton w3)))
 
 -- extended keys --------------------------------------------------------------
 
--- | A public or private key, extended with a chain code.
-data X a = X !a !BS.ByteString
-  deriving (Eq, Show)
-
 -- | An extended public key.
 newtype XPub = XPub (X Secp256k1.Projective)
   deriving (Eq, Show)
@@ -112,7 +112,22 @@
 newtype XPrv = XPrv (X Integer)
   deriving (Eq, Show)
 
+-- | A public or private key, extended with a chain code.
+data X a = X !a !BS.ByteString
+  deriving (Eq, Show)
+
 -- | Key types supporting identifier/fingerprint calculation.
+--
+--   >>> let Just hd = master "my very secret entropy"
+--   >>> let Right my_xprv = hd_key hd
+--   >>> let my_xpub = n k
+--   >>> -- all have the same fingerprint
+--   >>> fingerprint hd
+--   "G\157\&8\146"
+--   >>> fingerprint my_xprv
+--   "G\157\&8\146"
+--   >>> fingerprint my_xpub
+--   "G\157\&8\146"
 class Extended k where
   -- | Calculate the identifier for an extended key.
   identifier  :: k -> BS.ByteString
@@ -206,6 +221,10 @@
 -- | Derive a master 'HDKey' from a master seed.
 --
 --   Fails with 'Nothing' if the provided seed has an invalid length.
+--
+---  >>> let Just hd = master "my very secret entropy"
+--   >>> xpub hd
+--   "xpub661MyMwAqRbcGTJPtZRqZyrvjxHCfhqXeiqb5GVU3EGuFBy4QxT3yt8iiHwZTiCzZFyuyNiqXB3eqzqFZ8z4L6HCrPSkDVFNuW59LXYvMjs"
 master :: BS.ByteString -> Maybe HDKey
 master seed = do
   m <- _master seed
@@ -219,6 +238,10 @@
 -- | Derive a private child node at the provided index.
 --
 --   Fails with 'Nothing' if derivation is impossible.
+--
+--   >>> let Just child_prv = derive_child_priv hd 0
+--   >>> xpub child_prv
+--   "xpub68R2ZbtFeJTFJApdEdPqW5cy3d5wF96tTfJErhu3mTi2Ttaqvc88BMPrgS3hQSrHj91kRbzVLM9pue9f8219szRKZuTAx1LWbdLDLFDm6Ly"
 derive_child_priv :: HDKey -> Word32 -> Maybe HDKey
 derive_child_priv HDKey {..} i = case hd_key of
   Left _ -> Nothing
@@ -232,18 +255,23 @@
 -- | Derive a public child node at the provided index.
 --
 --   Fails with 'Nothing' if derivation is impossible.
+--
+--   >>> :set -XNumericUnderscores
+--   >>> let Just child_pub = derive_child_pub child_prv 0x8000_0000
+--   >>> xpub child_pub
+--   "xpub6B6LoU83Cpyx1UVMwuoQdQvY2BuGbPd2xsEVxCnj85UGgDN9bRz82hQhe9UFmyo4Pokuhjc8M1Cfc8ufLxcL6FkCF7Zc2eajEfWfZwMFF6X"
 derive_child_pub :: HDKey -> Word32 -> Maybe HDKey
 derive_child_pub HDKey {..} i = do
   (key, parent) <- case hd_key of
     Left _xpub  -> do
       pub <- ckd_pub _xpub i
-      pure (pub, fingerprint _xpub)
+      pure $! (pub, fingerprint _xpub)
     Right _xprv ->
       let pub = n (ckd_priv _xprv i)
-      in  pure (pub, fingerprint _xprv)
+      in  pure $! (pub, fingerprint _xprv)
   let depth = hd_depth + 1
       child = ser32 i
-  pure $ HDKey (Left key) depth parent child
+  pure $! HDKey (Left key) depth parent child
 
 -- derivation path expression -------------------------------------------------
 
@@ -284,8 +312,10 @@
 --   Fails with 'Nothing' if derivation is impossible, or if the
 --   provided path is invalid.
 --
---   >>> let hd = master "my very secret master seed"
---   >>> derive hd "m/44'/0'/0'/0/0"
+--   >>> let Just hd = master "my very secret master seed"
+--   >>> let Just child = derive hd "m/44'/0'/0'/0/0"
+--   >>> xpub child
+--   "xpub6FvaeGNFmCkLky6jwefrUfyH7gCGSAUckRBANT6wLQkm4eWZApsf4LqAadtbM8EBFfuKGFgzhgta4ByP6xnBodk2EV7BiwxCPLgu13oYWGp"
 derive
   :: HDKey
   -> BS.ByteString -- ^ derivation path
@@ -308,8 +338,9 @@
 --   Fails with 'error' if derivation is impossible, or if the provided
 --   path is invalid.
 --
---   >>> let hd = master "my very secret master seed"
---   >>> derive hd "m/44'/0'/0'/0/0"
+--   >>> let Just other_child = derive hd "m/44'/0'/0'/0/1"
+--   >>> xpub other_child
+--   "xpub6FvaeGNFmCkLpkT3uahJnGPTfEX62PtH7uZAyjtru8S2FvPuYTQKn8ct6CNQAwHMXaGN6EYuwi1Tz2VD7msftH8VTAtzgNra9CForA9FBP4"
 derive_partial
   :: HDKey
   -> BS.ByteString
@@ -339,6 +370,10 @@
 _TESTNET_PRV_BYTES = "\EOT5\131\148"
 
 -- | Serialize a mainnet extended public key in base58check format.
+--
+--   >>> let Just hd = master "my very secret entropy"
+--   >>> xpub hd
+--   "xpub661MyMwAqRbcGTJPtZRqZyrvjxHCfhqXeiqb5GVU3EGuFBy4QxT3yt8iiHwZTiCzZFyuyNiqXB3eqzqFZ8z4L6HCrPSkDVFNuW59LXYvMjs"
 xpub :: HDKey -> BS.ByteString
 xpub x@HDKey {..} = B58C.encode . BS.toStrict . BSB.toLazyByteString $
   case hd_key of
@@ -349,6 +384,9 @@
       }
 
 -- | Serialize a mainnet extended private key in base58check format.
+--
+--   >>> xprv hd
+--   "xprv9s21ZrQH143K3yDvnXtqCqvCBvSiGF7gHVuzGt5rUtjvNPdusR8oS5pErywDM1jDDTcLpNNCbg9a9NuidBczRzSUp7seDeu8am64h6nfdrg"
 xprv :: HDKey -> BS.ByteString
 xprv x@HDKey {..} = B58C.encode . BS.toStrict . BSB.toLazyByteString $
   case hd_key of
@@ -356,6 +394,9 @@
     Right _ -> _serialize _MAINNET_PRV x
 
 -- | Serialize a testnet extended public key in base58check format.
+--
+--   >>> tpub hd
+--   "tpubD6NzVbkrYhZ4YFVFLkQvmuCJ55Nrf6LbCMRtRpYcP92nzUdmVBJ98KoYxL2LzDAEMAWpaxEi4GshYBKrwzqJDXjVuzC3u1ucVTfZ6ZD415x"
 tpub :: HDKey -> BS.ByteString
 tpub x@HDKey {..} = B58C.encode . BS.toStrict . BSB.toLazyByteString $
   case hd_key of
@@ -366,6 +407,9 @@
       }
 
 -- | Serialize a testnet extended private key in base58check format.
+--
+--   >>> tprv hd
+--   "tprv8ZgxMBicQKsPenTTT6kLNVYBW3rvVm9gd3q79JWJxsEQ9zNzrnUYwqBgnA6sMP7Xau97pTyxm2jNcETTkPxwF3i5Lm5wt1dBVrqV8kKi5v5"
 tprv :: HDKey -> BS.ByteString
 tprv x@HDKey {..} = B58C.encode . BS.toStrict . BSB.toLazyByteString $
   case hd_key of
@@ -396,6 +440,11 @@
 -- | Parse a base58check-encoded 'ByteString' into a 'HDKey'.
 --
 --   Fails with 'Nothing' if the provided key is invalid.
+--
+--   >>> let Just hd = master "my very secret entropy"
+--   >>> let Just my_xprv = parse (xprv hd)
+--   >>> my_xprv == hd
+--   True
 parse :: BS.ByteString -> Maybe HDKey
 parse b58 = do
     bs <- B58C.decode b58
diff --git a/ppad-bip32.cabal b/ppad-bip32.cabal
--- a/ppad-bip32.cabal
+++ b/ppad-bip32.cabal
@@ -1,6 +1,6 @@
 cabal-version:      3.0
 name:               ppad-bip32
-version:            0.1.0
+version:            0.1.1
 synopsis:           BIP32 hierarchical deterministic wallets.
 license:            MIT
 license-file:       LICENSE
