diff --git a/rtcm.cabal b/rtcm.cabal
--- a/rtcm.cabal
+++ b/rtcm.cabal
@@ -1,5 +1,5 @@
 name:                  rtcm
-version:               0.1.4
+version:               0.1.5
 synopsis:              RTCM Library.
 description:           Haskell bindings for RTCM.
 homepage:              http://github.com/swift-nav/librtcm
diff --git a/src/Data/RTCM3.hs b/src/Data/RTCM3.hs
--- a/src/Data/RTCM3.hs
+++ b/src/Data/RTCM3.hs
@@ -17,6 +17,7 @@
   ) where
 
 import BasicPrelude
+import Control.Lens
 import Data.Binary
 import Data.ByteString.Lazy
 import Data.RTCM3.Antennas
@@ -29,68 +30,90 @@
 -- Includes RTCMMsgUnknown for valid RTCM messages with undefined message
 -- types and RTCMMsgBadCRC for RTCM messages with invalid CRC checksums.
 data RTCM3Msg =
-     RTCM3Msg1001 Msg1001 Msg
-   | RTCM3Msg1002 Msg1002 Msg
-   | RTCM3Msg1003 Msg1003 Msg
-   | RTCM3Msg1004 Msg1004 Msg
-   | RTCM3Msg1005 Msg1005 Msg
-   | RTCM3Msg1006 Msg1006 Msg
-   | RTCM3Msg1007 Msg1007 Msg
-   | RTCM3Msg1008 Msg1008 Msg
-   | RTCM3Msg1009 Msg1009 Msg
-   | RTCM3Msg1010 Msg1010 Msg
-   | RTCM3Msg1011 Msg1011 Msg
-   | RTCM3Msg1012 Msg1012 Msg
-   | RTCM3Msg1013 Msg1013 Msg
-   | RTCM3Msg1033 Msg1033 Msg
-   | RTCM3Msg1230 Msg1230 Msg
-   | RTCM3MsgUnknown Word16 Msg
-   | RTCM3MsgBadCrc Msg
+     RTCM3Msg1001    Msg1001 Msg
+   | RTCM3Msg1002    Msg1002 Msg
+   | RTCM3Msg1003    Msg1003 Msg
+   | RTCM3Msg1004    Msg1004 Msg
+   | RTCM3Msg1005    Msg1005 Msg
+   | RTCM3Msg1006    Msg1006 Msg
+   | RTCM3Msg1007    Msg1007 Msg
+   | RTCM3Msg1008    Msg1008 Msg
+   | RTCM3Msg1009    Msg1009 Msg
+   | RTCM3Msg1010    Msg1010 Msg
+   | RTCM3Msg1011    Msg1011 Msg
+   | RTCM3Msg1012    Msg1012 Msg
+   | RTCM3Msg1013    Msg1013 Msg
+   | RTCM3Msg1033    Msg1033 Msg
+   | RTCM3Msg1230    Msg1230 Msg
+   | RTCM3MsgUnknown         Msg
+   | RTCM3MsgBadCrc          Msg
    deriving ( Show, Read, Eq )
 
+$(makePrisms ''RTCM3Msg)
+
 instance Binary RTCM3Msg where
   get = do
     preamble <- getWord8
     if preamble /= msgRTCM3Preamble then get else do
-      rtcm3 <- get
-      return $ decode' rtcm3  where
-        decode' rtcm3@Msg {..}
-          | checkCrc _msgRTCM3Len _msgRTCM3Payload /= _msgRTCM3Crc = RTCM3MsgBadCrc rtcm3
-          | num == msg1001 = RTCM3Msg1001 (decode $ fromStrict _msgRTCM3Payload) rtcm3
-          | num == msg1002 = RTCM3Msg1002 (decode $ fromStrict _msgRTCM3Payload) rtcm3
-          | num == msg1003 = RTCM3Msg1003 (decode $ fromStrict _msgRTCM3Payload) rtcm3
-          | num == msg1004 = RTCM3Msg1004 (decode $ fromStrict _msgRTCM3Payload) rtcm3
-          | num == msg1005 = RTCM3Msg1005 (decode $ fromStrict _msgRTCM3Payload) rtcm3
-          | num == msg1006 = RTCM3Msg1006 (decode $ fromStrict _msgRTCM3Payload) rtcm3
-          | num == msg1007 = RTCM3Msg1007 (decode $ fromStrict _msgRTCM3Payload) rtcm3
-          | num == msg1008 = RTCM3Msg1008 (decode $ fromStrict _msgRTCM3Payload) rtcm3
-          | num == msg1009 = RTCM3Msg1009 (decode $ fromStrict _msgRTCM3Payload) rtcm3
-          | num == msg1010 = RTCM3Msg1010 (decode $ fromStrict _msgRTCM3Payload) rtcm3
-          | num == msg1011 = RTCM3Msg1011 (decode $ fromStrict _msgRTCM3Payload) rtcm3
-          | num == msg1012 = RTCM3Msg1012 (decode $ fromStrict _msgRTCM3Payload) rtcm3
-          | num == msg1013 = RTCM3Msg1013 (decode $ fromStrict _msgRTCM3Payload) rtcm3
-          | num == msg1033 = RTCM3Msg1033 (decode $ fromStrict _msgRTCM3Payload) rtcm3
-          | num == msg1230 = RTCM3Msg1230 (decode $ fromStrict _msgRTCM3Payload) rtcm3
-          | otherwise = RTCM3MsgUnknown num rtcm3 where
+      decode' <$> get where
+        decode' m@Msg {..}
+          | crc /= _msgRTCM3Crc = RTCM3MsgBadCrc m
+          | num == msg1001 = RTCM3Msg1001 (decode $ fromStrict _msgRTCM3Payload) m
+          | num == msg1002 = RTCM3Msg1002 (decode $ fromStrict _msgRTCM3Payload) m
+          | num == msg1003 = RTCM3Msg1003 (decode $ fromStrict _msgRTCM3Payload) m
+          | num == msg1004 = RTCM3Msg1004 (decode $ fromStrict _msgRTCM3Payload) m
+          | num == msg1005 = RTCM3Msg1005 (decode $ fromStrict _msgRTCM3Payload) m
+          | num == msg1006 = RTCM3Msg1006 (decode $ fromStrict _msgRTCM3Payload) m
+          | num == msg1007 = RTCM3Msg1007 (decode $ fromStrict _msgRTCM3Payload) m
+          | num == msg1008 = RTCM3Msg1008 (decode $ fromStrict _msgRTCM3Payload) m
+          | num == msg1009 = RTCM3Msg1009 (decode $ fromStrict _msgRTCM3Payload) m
+          | num == msg1010 = RTCM3Msg1010 (decode $ fromStrict _msgRTCM3Payload) m
+          | num == msg1011 = RTCM3Msg1011 (decode $ fromStrict _msgRTCM3Payload) m
+          | num == msg1012 = RTCM3Msg1012 (decode $ fromStrict _msgRTCM3Payload) m
+          | num == msg1013 = RTCM3Msg1013 (decode $ fromStrict _msgRTCM3Payload) m
+          | num == msg1033 = RTCM3Msg1033 (decode $ fromStrict _msgRTCM3Payload) m
+          | num == msg1230 = RTCM3Msg1230 (decode $ fromStrict _msgRTCM3Payload) m
+          | otherwise = RTCM3MsgUnknown m where
+            crc = checkCrc _msgRTCM3Len _msgRTCM3Payload
             num = checkNum _msgRTCM3Payload
 
-  put msg = do
+  put rm = do
     putWord8 msgRTCM3Preamble
-    encode' msg where
-      encode' (RTCM3Msg1001 _msg rtcm3) = put rtcm3
-      encode' (RTCM3Msg1002 _msg rtcm3) = put rtcm3
-      encode' (RTCM3Msg1003 _msg rtcm3) = put rtcm3
-      encode' (RTCM3Msg1004 _msg rtcm3) = put rtcm3
-      encode' (RTCM3Msg1005 _msg rtcm3) = put rtcm3
-      encode' (RTCM3Msg1006 _msg rtcm3) = put rtcm3
-      encode' (RTCM3Msg1007 _msg rtcm3) = put rtcm3
-      encode' (RTCM3Msg1008 _msg rtcm3) = put rtcm3
-      encode' (RTCM3Msg1009 _msg rtcm3) = put rtcm3
-      encode' (RTCM3Msg1010 _msg rtcm3) = put rtcm3
-      encode' (RTCM3Msg1011 _msg rtcm3) = put rtcm3
-      encode' (RTCM3Msg1012 _msg rtcm3) = put rtcm3
-      encode' (RTCM3Msg1013 _msg rtcm3) = put rtcm3
-      encode' (RTCM3Msg1033 _msg rtcm3) = put rtcm3
-      encode' (RTCM3Msg1230 _msg rtcm3) = put rtcm3
-      encode' (RTCM3MsgUnknown _num rtcm3) = put rtcm3
-      encode' (RTCM3MsgBadCrc rtcm3) = put rtcm3
+    encode' rm where
+      encode' (RTCM3Msg1001    _n m) = put m
+      encode' (RTCM3Msg1002    _n m) = put m
+      encode' (RTCM3Msg1003    _n m) = put m
+      encode' (RTCM3Msg1004    _n m) = put m
+      encode' (RTCM3Msg1005    _n m) = put m
+      encode' (RTCM3Msg1006    _n m) = put m
+      encode' (RTCM3Msg1007    _n m) = put m
+      encode' (RTCM3Msg1008    _n m) = put m
+      encode' (RTCM3Msg1009    _n m) = put m
+      encode' (RTCM3Msg1010    _n m) = put m
+      encode' (RTCM3Msg1011    _n m) = put m
+      encode' (RTCM3Msg1012    _n m) = put m
+      encode' (RTCM3Msg1013    _n m) = put m
+      encode' (RTCM3Msg1033    _n m) = put m
+      encode' (RTCM3Msg1230    _n m) = put m
+      encode' (RTCM3MsgUnknown    m) = put m
+      encode' (RTCM3MsgBadCrc     m) = put m
+
+instance HasMsg RTCM3Msg where
+  msg f (RTCM3Msg1001    n m) = RTCM3Msg1001    n <$> f m
+  msg f (RTCM3Msg1002    n m) = RTCM3Msg1002    n <$> f m
+  msg f (RTCM3Msg1003    n m) = RTCM3Msg1003    n <$> f m
+  msg f (RTCM3Msg1004    n m) = RTCM3Msg1004    n <$> f m
+  msg f (RTCM3Msg1005    n m) = RTCM3Msg1005    n <$> f m
+  msg f (RTCM3Msg1006    n m) = RTCM3Msg1006    n <$> f m
+  msg f (RTCM3Msg1007    n m) = RTCM3Msg1007    n <$> f m
+  msg f (RTCM3Msg1008    n m) = RTCM3Msg1008    n <$> f m
+  msg f (RTCM3Msg1009    n m) = RTCM3Msg1009    n <$> f m
+  msg f (RTCM3Msg1010    n m) = RTCM3Msg1010    n <$> f m
+  msg f (RTCM3Msg1011    n m) = RTCM3Msg1011    n <$> f m
+  msg f (RTCM3Msg1012    n m) = RTCM3Msg1012    n <$> f m
+  msg f (RTCM3Msg1013    n m) = RTCM3Msg1013    n <$> f m
+  msg f (RTCM3Msg1033    n m) = RTCM3Msg1033    n <$> f m
+  msg f (RTCM3Msg1230    n m) = RTCM3Msg1230    n <$> f m
+  msg f (RTCM3MsgUnknown   m) = RTCM3MsgUnknown   <$> f m
+  msg f (RTCM3MsgBadCrc    m) = RTCM3MsgBadCrc    <$> f m
+
diff --git a/src/Data/RTCM3/TH.hs b/src/Data/RTCM3/TH.hs
--- a/src/Data/RTCM3/TH.hs
+++ b/src/Data/RTCM3/TH.hs
@@ -22,8 +22,8 @@
 deriveRTCM3 :: Name -> Q [Dec]
 deriveRTCM3 name =
   [d|instance ToRTCM3 $(conT name) where
-       toRTCM3 msg = Msg len payload crc where
-         payload = toStrict $ encode msg
-         len     = fromIntegral $ length payload
-         crc     = checkCrc len payload
+       toRTCM3 n = Msg len pay crc where
+         pay = toStrict $ encode n
+         len = fromIntegral $ length pay
+         crc = checkCrc len pay
     |]
diff --git a/src/Data/RTCM3/Types.hs b/src/Data/RTCM3/Types.hs
--- a/src/Data/RTCM3/Types.hs
+++ b/src/Data/RTCM3/Types.hs
@@ -32,7 +32,7 @@
   , _msgRTCM3Crc     :: Word24
   } deriving ( Show, Read, Eq )
 
-$(makeLenses ''Msg)
+$(makeClassy ''Msg)
 
 instance Binary Msg where
   get = do
@@ -42,14 +42,9 @@
     return Msg {..}
 
   put Msg {..} = do
-    putWord16be _msgRTCM3Len
+    putWord16be   _msgRTCM3Len
     putByteString _msgRTCM3Payload
-    putWord24be _msgRTCM3Crc
-
-checkNum :: ByteString -> Word16
-checkNum payload =
-  flip runGet (fromStrict payload) $ B.runBitGet $
-    B.getWord16be 12
+    putWord24be   _msgRTCM3Crc
 
 checkCrc :: Word16 -> ByteString -> Word24
 checkCrc len payload =
@@ -58,5 +53,14 @@
     word16BE len            <>
     byteString payload
 
+checkNum :: ByteString -> Word16
+checkNum payload =
+  flip runGet (fromStrict payload) $ B.runBitGet $
+    B.getWord16be 12
+
+msgRTCM3Num :: HasMsg m => m -> Word16
+msgRTCM3Num = checkNum . (^. msgRTCM3Payload)
+
 class Binary a => ToRTCM3 a where
   toRTCM3 :: a -> Msg
+
diff --git a/test/Test/Data/RTCM3/Antennas.hs b/test/Test/Data/RTCM3/Antennas.hs
--- a/test/Test/Data/RTCM3/Antennas.hs
+++ b/test/Test/Data/RTCM3/Antennas.hs
@@ -80,28 +80,28 @@
 
 testMsg1005 :: TestTree
 testMsg1005 =
-  testProperty "Roundtrip Msg1005" $ \msg ->
-    (decode $ encode msg) == (msg :: Msg1005)
+  testProperty "Roundtrip Msg1005" $ \m ->
+    (decode $ encode m) == (m :: Msg1005)
 
 testMsg1006 :: TestTree
 testMsg1006 =
-  testProperty "Roundtrip Msg1006" $ \msg ->
-    (decode $ encode msg) == (msg :: Msg1006)
+  testProperty "Roundtrip Msg1006" $ \m ->
+    (decode $ encode m) == (m :: Msg1006)
 
 testMsg1007 :: TestTree
 testMsg1007 =
-  testProperty "Roundtrip Msg1007" $ \msg ->
-    (decode $ encode msg) == (msg :: Msg1007)
+  testProperty "Roundtrip Msg1007" $ \m ->
+    (decode $ encode m) == (m :: Msg1007)
 
 testMsg1008 :: TestTree
 testMsg1008 =
-  testProperty "Roundtrip Msg1008" $ \msg ->
-    (decode $ encode msg) == (msg :: Msg1008)
+  testProperty "Roundtrip Msg1008" $ \m ->
+    (decode $ encode m) == (m :: Msg1008)
 
 testMsg1033 :: TestTree
 testMsg1033 =
-  testProperty "Roundtrip Msg1033" $ \msg ->
-    (decode $ encode msg) == (msg :: Msg1033)
+  testProperty "Roundtrip Msg1033" $ \m ->
+    (decode $ encode m) == (m :: Msg1033)
 
 tests :: TestTree
 tests =
diff --git a/test/Test/Data/RTCM3/Observations.hs b/test/Test/Data/RTCM3/Observations.hs
--- a/test/Test/Data/RTCM3/Observations.hs
+++ b/test/Test/Data/RTCM3/Observations.hs
@@ -186,48 +186,48 @@
 
 testMsg1001 :: TestTree
 testMsg1001 =
-  testProperty "Roundtrip Msg1001" $ \msg ->
-    (decode $ encode msg) == (msg :: Msg1001)
+  testProperty "Roundtrip Msg1001" $ \m ->
+    (decode $ encode m) == (m :: Msg1001)
 
 testMsg1002 :: TestTree
 testMsg1002 =
-  testProperty "Roundtrip Msg1002" $ \msg ->
-    (decode $ encode msg) == (msg :: Msg1002)
+  testProperty "Roundtrip Msg1002" $ \m ->
+    (decode $ encode m) == (m :: Msg1002)
 
 testMsg1003 :: TestTree
 testMsg1003 =
-  testProperty "Roundtrip Msg1003" $ \msg ->
-    (decode $ encode msg) == (msg :: Msg1003)
+  testProperty "Roundtrip Msg1003" $ \m ->
+    (decode $ encode m) == (m :: Msg1003)
 
 testMsg1004 :: TestTree
 testMsg1004 =
-  testProperty "Roundtrip Msg1004" $ \msg ->
-    (decode $ encode msg) == (msg :: Msg1004)
+  testProperty "Roundtrip Msg1004" $ \m ->
+    (decode $ encode m) == (m :: Msg1004)
 
 testMsg1009 :: TestTree
 testMsg1009 =
-  testProperty "Roundtrip Msg1009" $ \msg ->
-    (decode $ encode msg) == (msg :: Msg1009)
+  testProperty "Roundtrip Msg1009" $ \m ->
+    (decode $ encode m) == (m :: Msg1009)
 
 testMsg1010 :: TestTree
 testMsg1010 =
-  testProperty "Roundtrip Msg1010" $ \msg ->
-    (decode $ encode msg) == (msg :: Msg1010)
+  testProperty "Roundtrip Msg1010" $ \m ->
+    (decode $ encode m) == (m :: Msg1010)
 
 testMsg1011 :: TestTree
 testMsg1011 =
-  testProperty "Roundtrip Msg1011" $ \msg ->
-    (decode $ encode msg) == (msg :: Msg1011)
+  testProperty "Roundtrip Msg1011" $ \m ->
+    (decode $ encode m) == (m :: Msg1011)
 
 testMsg1012 :: TestTree
 testMsg1012 =
-  testProperty "Roundtrip Msg1012" $ \msg ->
-    (decode $ encode msg) == (msg :: Msg1012)
+  testProperty "Roundtrip Msg1012" $ \m ->
+    (decode $ encode m) == (m :: Msg1012)
 
 testMsg1230 :: TestTree
 testMsg1230 =
-  testProperty "Roundtrip Msg1230" $ \msg ->
-    (decode $ encode msg) == (msg :: Msg1230)
+  testProperty "Roundtrip Msg1230" $ \m ->
+    (decode $ encode m) == (m :: Msg1230)
 
 tests :: TestTree
 tests =
diff --git a/test/Test/Data/RTCM3/System.hs b/test/Test/Data/RTCM3/System.hs
--- a/test/Test/Data/RTCM3/System.hs
+++ b/test/Test/Data/RTCM3/System.hs
@@ -45,8 +45,8 @@
 
 testMsg1013 :: TestTree
 testMsg1013 =
-  testProperty "Roundtrip Msg1013" $ \msg ->
-    (decode $ encode msg) == (msg :: Msg1013)
+  testProperty "Roundtrip Msg1013" $ \m ->
+    (decode $ encode m) == (m :: Msg1013)
 
 tests :: TestTree
 tests =
