diff --git a/GroteTrap.cabal b/GroteTrap.cabal
--- a/GroteTrap.cabal
+++ b/GroteTrap.cabal
@@ -1,29 +1,38 @@
 Name:           GroteTrap
-Version:        0.5
+Version:        0.5.1
 Synopsis:       Parser and selection library for expression languages.
 Description:    Allows quick definition of expression languages. You get a parser for free, as well as conversion from text selection to tree selection and back.
 Homepage:       http://www.haskell.org/haskellwiki/GroteTrap
 
 Author:         Jeroen Leeuwestein, Martijn van Steenbergen
 Maintainer:     martijn@van.steenbergen.nl
-Copyright:      Copyright (c) 2007-2008 Jeroen Leeuwestein and Martijn van Steenbergen
+Copyright:      Copyright (c) 2007-2015 Jeroen Leeuwestein and Martijn van Steenbergen
 
-Cabal-Version:  >= 1.2
+Cabal-Version:  >= 1.6
 License:        BSD3
 License-file:   LICENSE
 Category:       Language
 Build-type:     Simple
 Extra-source-files: LogicExample.hs, ArithmeticExample.hs
 
+Source-Repository head
+  Type:         git
+  Location:     https://github.com/MedeaMelana/GroteTrap
+
 Library
-  Build-Depends:    base, QuickCheck, parsec <= 2.1.0.0, mtl
+  Build-Depends:    base < 5,
+                    QuickCheck < 2.9,
+                    parsec < 3.2,
+                    mtl < 2.3,
+                    syb < 0.5
   Exposed-Modules:  Language.GroteTrap
-                    Language.GroteTrap.Range
-                    Language.GroteTrap.Trees
                     Language.GroteTrap.Language
                     Language.GroteTrap.Lexer
-                    Language.GroteTrap.Unparse
+                    Language.GroteTrap.Range
+                    Language.GroteTrap.Show
                     Language.GroteTrap.ShowTree
+                    Language.GroteTrap.Trees
+                    Language.GroteTrap.Unparse
                     Language.GroteTrap.Util
   Other-Modules:    Language.GroteTrap.ParseTree
                     Language.GroteTrap.Parser
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2008, Jeroen Leeuwestein and Martijn van Steenbergen
+Copyright (c) 2008-2015, Jeroen Leeuwestein and Martijn van Steenbergen
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/Language/GroteTrap.hs b/Language/GroteTrap.hs
--- a/Language/GroteTrap.hs
+++ b/Language/GroteTrap.hs
@@ -7,6 +7,7 @@
   module Language.GroteTrap.Unparse,
   module Language.GroteTrap.ShowTree,
   module Language.GroteTrap.Util,
+  module Language.GroteTrap.Show,
 
   -- * Parsing and evaluating
   
@@ -26,3 +27,4 @@
 import Language.GroteTrap.Unparse
 import Language.GroteTrap.ShowTree
 import Language.GroteTrap.Util
+import Language.GroteTrap.Show
diff --git a/Language/GroteTrap/Language.hs b/Language/GroteTrap/Language.hs
--- a/Language/GroteTrap/Language.hs
+++ b/Language/GroteTrap/Language.hs
@@ -25,8 +25,8 @@
 
 -- | Language connects the syntax of identifiers, numbers, operators and functions with their semantics. GroteTrap is able to derive a parser and evaluator from a Language, as well as convert between source text selections and tree selections.
 data Language a  =   Language
-  { variable     ::  String -> a
-  , number       ::  Int -> a
+  { variable     ::  Maybe (String -> a)
+  , number       ::  Maybe (Int -> a)
   , operators    ::  [Operator a]
   , functions    ::  [Function a]
   }
@@ -34,8 +34,8 @@
 -- | An empty language. Use this as the starting base of your languages, setting only those fields that are of importance.
 language :: Language a
 language = Language
-  { variable    = error "variables are not supported"
-  , number      = error "numbers are not supported"
+  { variable    = Nothing
+  , number      = Nothing
   , operators   = []
   , functions   = []
   }
diff --git a/Language/GroteTrap/ParseTree.hs b/Language/GroteTrap/ParseTree.hs
--- a/Language/GroteTrap/ParseTree.hs
+++ b/Language/GroteTrap/ParseTree.hs
@@ -78,8 +78,8 @@
 -- | Evaluates a parse tree from a language.
 evaluate :: Language a -> ParseTree -> a
 evaluate lang = foldParseTree (ParseTreeAlg eid eint euna ebin elst ecll epar) where
-  eid  _            = variable lang
-  eint _            = number   lang
+  eid  _            = fromJust $ variable lang
+  eint _            = fromJust $ number   lang
   euna _ op         = opSem1  $ fromJust $ findOperator op isUnary  $ operators lang
   ebin _ op         = opSem2  $ fromJust $ findOperator op isBinary $ operators lang
   elst _ op         = opSemN  $ fromJust $ findOperator op isAssoc  $ operators lang
diff --git a/Language/GroteTrap/Show.hs b/Language/GroteTrap/Show.hs
new file mode 100644
--- /dev/null
+++ b/Language/GroteTrap/Show.hs
@@ -0,0 +1,49 @@
+module Language.GroteTrap.Show (lshow, format) where
+
+import Data.Maybe
+import Data.List
+import Data.Generics hiding (Prefix)
+import Language.GroteTrap.Language
+import Language.GroteTrap.Parser
+
+lshow lang = lshow' lang maxBound
+
+lshow' :: Data a => Language a -> Int -> a -> String
+lshow' lang contextPrio val =
+  if isJust (variable lang) && con == toConstr (fromJust (variable lang) undefined)
+  then fromJust $ gfindtype val
+  else if isJust (number lang) && con == toConstr (fromJust (number lang) undefined)
+  then show $ (fromJust $ gfindtype val :: Int)
+  else fromJust $ lookup con [ (toConstr $ opCon op, lshow'Op lang contextPrio op val) | op <- operators lang ]
+  where
+    con = toConstr val
+
+opCon :: Operator a -> a
+opCon (Unary { opSem1 = o }) = o undefined
+opCon (Binary { opSem2 = o }) = o undefined undefined
+opCon (Assoc { opSemN = o }) = o undefined
+
+gchildren :: (Data a, Typeable b) => a -> [b]
+gchildren v = catMaybes $ gmapQ (Nothing `mkQ` Just) v
+
+lshow'Op :: Data a => Language a -> Int -> Operator a -> a -> String
+lshow'Op lang contextPrio op val = par $ case (op, gchildren val) of
+    (Unary _ Prefix prio tok, [c]) ->
+      tok ++ sh prio c
+    (Unary _ Postfix prio tok, [c]) ->
+      sh prio c ++ tok
+    (Binary _ _ prio tok, [lhs, rhs]) ->
+      sh prio lhs ++ " " ++ tok ++ " " ++ sh prio rhs
+    (Assoc _ prio tok, _) ->
+      concat $ intersperse (" " ++ tok ++ " ") $ map (sh prio) (head (gchildren val))
+    _ ->
+      error "unexpected number of children"
+  where
+    sh = lshow' lang
+    par s
+      | opPrio op >= contextPrio  = "(" ++ s ++ ")"
+      | otherwise                 = s
+
+-- | Formats a sentence according to a language.
+format :: Data a => Language a -> String -> String
+format lang = lshow lang . readExpression lang
diff --git a/Language/GroteTrap/Unparse.hs b/Language/GroteTrap/Unparse.hs
--- a/Language/GroteTrap/Unparse.hs
+++ b/Language/GroteTrap/Unparse.hs
@@ -73,7 +73,7 @@
 over upper lower = take n $ zipWith f (pad upper) (pad lower)
   where f ' ' b = b
         f  a  _ = a
-        pad str = str ++ repeat ' '
+        pad = (++ repeat ' ')
         n = length upper `max` length lower
 
 -- | Merge folds many strings 'over' each other.
diff --git a/LogicExample.hs b/LogicExample.hs
--- a/LogicExample.hs
+++ b/LogicExample.hs
@@ -1,6 +1,9 @@
+{-# OPTIONS -fglasgow-exts #-}
+
 module LogicExample where
 
 import Language.GroteTrap
+import Data.Generics hiding (Prefix)
 
 import Data.Set hiding (map)
 
@@ -13,7 +16,7 @@
   | And [Logic]
   | Impl Logic Logic
   | Not Logic
-  deriving (Show, Eq)
+  deriving (Show, Eq, Typeable, Data)
 
 type LogicAlg a =
   ( String -> a
@@ -36,7 +39,7 @@
 
 logicLanguage :: Language Logic
 logicLanguage = language
-  { variable  = Var
+  { variable  = Just Var
   , operators =
       [ Unary    Not  Prefix  0 "!"
       , Assoc    And          1 "&&"
@@ -68,3 +71,4 @@
 demo4 = fromError $ follow appie root
 demo5 = fromError $ follow appie [0]
 demo6 = range $ fromError $ follow appie [0]
+demo7 = lshow logicLanguage (And [Var "p", Var "q"])
