diff --git a/Language/Nock5K.hs b/Language/Nock5K.hs
--- a/Language/Nock5K.hs
+++ b/Language/Nock5K.hs
@@ -1,4 +1,4 @@
-module Language.Nock5K (Noun(Atom, (:-)), nock, noun, repl) where
+module Language.Nock5K (Noun(Atom, (:-)), Nock, nock, noun, repl) where
 
 import Language.Nock5K.Parse
 import Language.Nock5K.Repl
diff --git a/Language/Nock5K/Spec.hs b/Language/Nock5K/Spec.hs
new file mode 100644
--- /dev/null
+++ b/Language/Nock5K/Spec.hs
@@ -0,0 +1,123 @@
+{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
+module Language.Nock5K.Spec where
+
+-- * Structures
+{-|
+  A noun is an atom or a cell.  An atom is any natural number.
+  A cell is an ordered pair of nouns.
+-}
+data Noun = Atom Integer | Noun :- Noun deriving (Eq)
+
+-- | Either a computed result or an error message.
+-- E.g. Nock Noun is either a Noun or an error.
+type Nock = Either String
+instance Monad Nock where
+  return = Right
+  fail = Left
+  Right n >>= f = f n
+  Left e >>= _ = Left e
+
+-- * Reductions
+{-|@
+  nock(a)           *a
+@-}
+nock = tar
+
+{-
+  [a b c]           [a [b c]]
+-}
+infixr 1 :-
+
+nock, wut, lus, tis, fas, tar :: Noun -> Nock Noun
+
+{-|@
+  ?[a b]            0
+  ?a                1
+@-}
+wut (a :- b)  = return $ Atom 0
+wut a         = return $ Atom 1
+
+{-|@
+  +[a b]            +[a b]
+  +a                1 + a
+@-}
+lus (a :- b)  = fail "+[a b]"
+lus (Atom a)  = return $ Atom (1 + a)
+
+{-|@
+  =[a a]            0
+  =[a b]            1
+  =a                =a
+@-}
+tis (a :- a') | a == a'  = return $ Atom 0
+tis (a :- b)             = return $ Atom 1
+tis a                    = fail "=a"
+
+{-|@
+  \/[1 a]            a
+  \/[2 a b]          a
+  \/[3 a b]          b
+  \/[(a + a) b]      \/[2 \/[a b]]
+  \/[(a + a + 1) b]  \/[3 \/[a b]]
+  \/a                \/a
+@-}
+fas (Atom 1 :- a)       = return a
+fas (Atom 2 :- a :- b)  = return a
+fas (Atom 3 :- a :- b)  = return b
+fas (Atom a :- b) | a > 2 && a `mod` 2 == 0 = do
+  x <- fas $ Atom (a `div` 2) :- b
+  fas $ Atom 2 :- x
+fas (Atom a :- b) | a > 3 && a `mod` 2 == 1 = do
+  x <- fas $ Atom (a `div` 2) :- b
+  fas $ Atom 3 :- x
+fas a                   = fail "/a"
+
+{-|@
+  \*[a [b c] d]      [\*[a b c] \*[a d]]
+
+\  \*[a 0 b]          \/[b a]
+  \*[a 1 b]          b
+  \*[a 2 b c]        \*[\*[a b] \*[a c]]
+  \*[a 3 b]          ?\*[a b]
+  \*[a 4 b]          +\*[a b]
+  \*[a 5 b]          =\*[a b]
+
+\  \*[a 6 b c d]      \*[a 2 [0 1] 2 [1 c d] [1 0] 2 [1 2 3] [1 0] 4 4 b]
+  \*[a 7 b c]        \*[a 2 b 1 c]
+  \*[a 8 b c]        \*[a 7 [[7 [0 1] b] 0 1] c]
+  \*[a 9 b c]        \*[a 7 c 2 [0 1] 0 b]
+  \*[a 10 [b c] d]   \*[a 8 c 7 [0 3] d]
+  \*[a 10 b c]       \*[a c]
+
+\  \*a                \*a
+@-}
+tar (a :- (b :- c) :- d)             = do x <- tar (a :- b :- c)
+                                          y <- tar (a :- d)
+                                          return $ x :- y
+
+tar (a :- Atom 0 :- b)               = fas $ b :- a
+tar (a :- Atom 1 :- b)               = return b
+tar (a :- Atom 2 :- b :- c)          = do  x <- tar (a :- b)
+                                           y <- tar (a :- c)
+                                           tar $ x :- y
+tar (a :- Atom 3 :- b)               = tar (a :- b) >>= wut
+tar (a :- Atom 4 :- b)               = tar (a :- b) >>= lus
+tar (a :- Atom 5 :- b)               = tar (a :- b) >>= tis
+
+tar (a :- Atom 6 :- b :- c :- d)     = tar (a :- Atom 2 :- (Atom 0 :- Atom 1) :-
+                                            Atom 2 :- (Atom 1 :- c :- d) :-
+                                            (Atom 1 :- Atom 0) :- Atom 2 :-
+                                            (Atom 1 :- Atom 2 :- Atom 3) :-
+                                            (Atom 1 :- Atom 0) :- Atom 4 :-
+                                            Atom 4 :- b)
+tar (a :- Atom 7 :- b :- c)          = tar (a :- Atom 2 :- b :- Atom 1 :- c)
+tar (a :- Atom 8 :- b :- c)          = tar (a :- Atom 7 :-
+                                            ((Atom 7 :- (Atom 0 :- Atom 1) :- b) :-
+                                             Atom 0 :- Atom 1) :- c)
+tar (a :- Atom 9 :- b :- c)          = tar (a :- Atom 7 :- c :- Atom 2 :-
+                                            (Atom 0 :- Atom 1) :- Atom 0 :- b)
+tar (a :- Atom 10 :- (b :- c) :- d)  = tar (a :- Atom 8 :- c :- Atom 7 :-
+                                            (Atom 0 :- Atom 3) :- d)
+tar (a :- Atom 10 :- b :- c)         = tar (a :- c)
+
+tar a                                = fail "*a"
diff --git a/Language/Nock5K/Spec.lhs b/Language/Nock5K/Spec.lhs
deleted file mode 100644
--- a/Language/Nock5K/Spec.lhs
+++ /dev/null
@@ -1,154 +0,0 @@
-
-> module Language.Nock5K.Spec where
-> import Control.Monad.Instances
-
-1 Structures
-
-  A noun is an atom or a cell.  An atom is any natural number.
-  A cell is an ordered pair of nouns.
-
-> data Noun = Atom Integer | Noun :- Noun deriving (Eq)
-> type Comp = Either String
-
-
-2 Reductions
-
-  nock(a)           *a
-
-> nock :: Noun -> Comp Noun
-> nock = tar
-
-  [a b c]           [a [b c]]
-
-> infixr 1 :-
-
-
-  ?[a b]            0
-
-> wut (a :- b) = return $ Atom 0
-
-  ?a                1
-
-> wut a = return $ Atom 1
-
-  +[a b]            +[a b]
-
-> lus (a :- b) = Left "+[a b]"
-
-  +a                1 + a
-
-> lus (Atom a) = return $ Atom (1 + a)
-
-  =[a a]            0
-
-> tis (a :- a') | a == a' = return $ Atom 0
-
-  =[a b]            1
-
-> tis (a :- b) = return $ Atom 1
-
-  =a                =a
-
-> tis a = Left "=a"
-
-
-  /[1 a]            a
-
-> fas (Atom 1 :- a) = return a
-
-  /[2 a b]          a
-
-> fas (Atom 2 :- a :- b) = return a
-
-  /[3 a b]          b
-
-> fas (Atom 3 :- a :- b) = return b
-
-  /[(a + a) b]      /[2 /[a b]]
-
-> fas (Atom a :- b) | a > 2 && a `mod` 2 == 0 = do
->   x <- fas $ Atom (a `div` 2) :- b
->   fas $ Atom 2 :- x
-
-  /[(a + a + 1) b]  /[3 /[a b]]
-
-> fas (Atom a :- b) | a > 3 && a `mod` 2 == 1 = do
->   x <- fas $ Atom (a `div` 2) :- b
->   fas $ Atom 3 :- x
-
-  /a                /a
-
-> fas a = Left "/a"
-
-
-  *[a [b c] d]      [*[a b c] *[a d]]
-
-> tar (a :- (b :- c) :- d) = do
->   x <- tar (a :- b :- c)
->   y <- tar (a :- d)
->   return $ x :- y
-
-
-  *[a 0 b]          /[b a]
-
-> tar (a :- (Atom 0 :- b)) = fas $ b :- a
-
-  *[a 1 b]          b
-
-> tar (a :- (Atom 1 :- b)) = return b
-
-  *[a 2 b c]        *[*[a b] *[a c]]
-
-> tar (a :- Atom 2 :- b :- c) = do
->   x <- tar (a :- b)
->   y <- tar (a :- c)
->   tar $ x :- y
-
-  *[a 3 b]          ?*[a b]
-
-> tar (a :- Atom 3 :- b) = tar (a :- b) >>= wut
-
-  *[a 4 b]          +*[a b]
-
-> tar (a :- Atom 4 :- b) = tar (a :- b) >>= lus
-
-  *[a 5 b]          =*[a b]
-
-> tar (a :- Atom 5 :- b) = tar (a :- b) >>= tis
-
-
-  *[a 6 b c d]      *[a 2 [0 1] 2 [1 c d] [1 0] 2 [1 2 3] [1 0] 4 4 b]
-
-> tar (a :- Atom 6 :- b :- c :- d) =
->   tar (a :- Atom 2 :- (Atom 0 :- Atom 1) :- Atom 2 :- (Atom 1 :- c :- d) :-
->        (Atom 1 :- Atom 0) :- Atom 2 :- (Atom 1 :- Atom 2 :- Atom 3) :-
->        (Atom 1 :- Atom 0) :- Atom 4 :- Atom 4 :- b)
-
-  *[a 7 b c]        *[a 2 b 1 c]
-
-> tar (a :- Atom 7 :- b :- c) = tar $ a :- Atom 2 :- b :- Atom 1 :- c
-
-  *[a 8 b c]        *[a 7 [[7 [0 1] b] 0 1] c]
-
-> tar (a :- Atom 8 :- b :- c) =
->   tar (a :- Atom 7 :- ((Atom 7 :- (Atom 0 :- Atom 1) :- b) :-
->         Atom 0 :- Atom 1) :- c)
-
-  *[a 9 b c]        *[a 7 c 2 [0 1] 0 b]
-
-> tar (a :- Atom 9 :- b :- c) =
->   tar (a :- Atom 7 :- c :- Atom 2 :- (Atom 0 :- Atom 1) :- Atom 0 :- b)
-
-  *[a 10 [b c] d]   *[a 8 c 7 [0 3] d]
-
-> tar (a :- Atom 10 :- (b :- c) :- d) = tar (a :- c) `seq`
->   tar (a :- Atom 8 :- c :- Atom 7 :- (Atom 0 :- Atom 3) :- d)
-
-  *[a 10 b c]       *[a c]
-
-> tar (a :- Atom 10 :- b :- c) = tar $ a :- c
-
-
-  *a                *a
-
-> tar a = Left "*a"
diff --git a/hsnock.cabal b/hsnock.cabal
--- a/hsnock.cabal
+++ b/hsnock.cabal
@@ -1,5 +1,5 @@
 name                 : hsnock
-version              : 0.3.1
+version              : 0.4.1
 category             : Language
 license              : PublicDomain
 synopsis             : Nock 5K interpreter.
