diff --git a/.gitignore b/.gitignore
index 9c975f121abf3137eda44530ea880e33ab094774..9a631c161cca74d926535103e0063b3a7c9262b0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+bin/
 doc/html
 doc/images
 
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 31ed2bf0abc49a84a589e7e4ff0f5fcfe43b453e..3cc336dfa7ec7df5ac8e88f4cd3d69be673c504b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -18,6 +18,8 @@ IF (NOT CMAKE_BUILD_TYPE)
  SET(CMAKE_BUILD_TYPE "DEBUG") 
 ENDIF (NOT CMAKE_BUILD_TYPE)
 
+SET(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
+
 SET(CMAKE_CXX_FLAGS_DEBUG "-g -Wall -D_REENTRANT")
 SET(CMAKE_CXX_FLAGS_RELEASE "-O3 -D_REENTRANT")
 
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index c21ef23e78736c90ff9874c96873175d74f905c3..2cfb4bebc8f093c43acdf22b7bf6e325732089ee 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,7 +1,7 @@
 # driver source files
-SET(sources imagine-planner.cpp)
+SET(sources imagine-planner.cpp types.cpp)
 # application header files
-SET(headers imagine-planner.h)
+SET(headers imagine-planner.h types.h)
 # locate the necessary dependencies
 # add the necessary include directories
 INCLUDE_DIRECTORIES(.)
diff --git a/src/examples/CMakeLists.txt b/src/examples/CMakeLists.txt
index 0e52b5a59e98661447b769a90a8ae72ab710c40c..0d77386b771a7412909d6a27b572a44f745b791c 100644
--- a/src/examples/CMakeLists.txt
+++ b/src/examples/CMakeLists.txt
@@ -1,3 +1,6 @@
+ADD_EXECUTABLE(types_test types_test.cpp)
+TARGET_LINK_LIBRARIES(types_test imagine-planner)
+
 # create an example application
 ADD_EXECUTABLE(imagine-planner_test imagine-planner_test.cpp)
 # link necessary libraries
diff --git a/src/examples/types_test.cpp b/src/examples/types_test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..74ca6ad1bd0e36ab4f84139e8d3d022c670c1e0e
--- /dev/null
+++ b/src/examples/types_test.cpp
@@ -0,0 +1,20 @@
+#include <iostream>
+#include "types.h"
+using namespace imagine_planner;
+
+const char* b2s(bool b)
+{
+  return b? "true" : "false";
+}
+
+int main(int argc, char* argv[])
+{
+  std::hash<Term> h;
+  Term* atom = new Atom("my_atom");
+  Term* atom_ = new Atom("another_atom");
+  std::cout << "Testing stream operator for Atom: " << *atom << std::endl;
+  std::cout << "Testing hash function for Atom: " << h(*atom) << std::endl;
+  std::cout << "Testing == operator (equal): " << b2s(*atom == *atom) << std::endl;
+  std::cout << "Testing == operator (not equal): " << b2s(*atom == *atom_) << std::endl;
+}
+
diff --git a/src/imagine-planner.cpp b/src/imagine-planner.cpp
index 764e4d579565085a72c6255b083be8ba2e41a5b5..3ec12725d53d977af12b82479d4359ab9507d26b 100644
--- a/src/imagine-planner.cpp
+++ b/src/imagine-planner.cpp
@@ -1,10 +1,10 @@
 #include "imagine-planner.h"
 
-CImagine-Planner::CImagine-Planner()
+CImaginePlanner::CImaginePlanner()
 {
 }
  
-CImagine-Planner::~CImagine-Planner()
+CImaginePlanner::~CImaginePlanner()
 {
 }
 
diff --git a/src/imagine-planner.h b/src/imagine-planner.h
index 025557cc3eb5653e1068cb143864018807de77a1..22c2a6fa6049aeb6874914318805913c2c15124f 100644
--- a/src/imagine-planner.h
+++ b/src/imagine-planner.h
@@ -1,11 +1,11 @@
-#ifndef _IMAGINE-PLANNER_H
-#define _IMAGINE-PLANNER_H
+#ifndef _IMAGINE_PLANNER_H_
+#define _IMAGINE_PLANNER_H_
 
-class CImagine-Planner
+class CImaginePlanner
 {
   public:
-    CImagine-Planner();
-    ~CImagine-Planner();
+    CImaginePlanner();
+    ~CImaginePlanner();
 };
 
 #endif
diff --git a/src/types.cpp b/src/types.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..09174c7399b75e4ba81a2e7efa05f85d38a85dbd
--- /dev/null
+++ b/src/types.cpp
@@ -0,0 +1,70 @@
+#include "types.h"
+#include <cmath>
+
+namespace imagine_planner
+{
+
+// Implementation of Atom's methods
+
+Atom::Atom(const std::string& name) : name_(name) {}
+
+bool Atom::operator==(const Term& other) const
+{
+  if (const Atom* c_other = dynamic_cast<const Atom*>(&other))
+  {
+    return c_other->name_ == this->name_;
+  }
+  return false;
+}
+
+std::size_t Atom::hash() const
+{
+  std::hash<std::string> h;
+  return h(name_);
+}
+
+// Implementation of Number's methods
+
+Number::Number(double number) : number_(number) {}
+
+bool Number::operator==(const Term& other) const
+{
+  if (const Number* c_other = dynamic_cast<const Number*>(&other))
+  {
+    return std::fabs(number_ - c_other->number_) < 1E-9;
+  }
+  return false;
+}
+
+std::size_t Number::hash() const
+{
+  std::hash<int> h;
+  return is_int()? h(int(number_)) : 0; // Return 0 for non-integer values to
+                                        // avoid problems in maps and sets
+}
+
+bool Number::is_int() const
+{
+  return std::fabs(number_ - int(number_)) < 1E-9;
+}
+
+// Implementation of stream operator
+
+std::ostream& operator<<(std::ostream& os, const Term& term)
+{
+  os << term.to_str();
+  return os;
+}
+
+} /* end imagine_planner namespace */
+
+namespace std
+{
+
+std::size_t hash<imagine_planner::Term>::operator()(const imagine_planner::Term& term) const
+{
+  return term.hash();
+}
+
+}
+
diff --git a/src/types.h b/src/types.h
new file mode 100644
index 0000000000000000000000000000000000000000..6b8b074f4341df0a81d74913454e58c222a83309
--- /dev/null
+++ b/src/types.h
@@ -0,0 +1,143 @@
+#ifndef _LIBIMAGINE_PLANNER_TYPES_H_
+#define _LIBIMAGINE_PLANNER_TYPES_H_
+
+#include <functional>
+#include <ostream>
+#include <string>
+#include <vector>
+
+namespace imagine_planner
+{
+
+/** 
+ * @brief Generic Term class.
+ */
+class Term
+{
+  public:
+
+    virtual std::string to_str() const =0; 
+
+    virtual bool is_ground() const =0;
+
+    virtual bool is_atomic() const =0;
+
+    virtual bool operator==(const Term& other) const =0;
+
+    virtual std::size_t hash() const =0;
+
+    virtual ~Term() {}
+};
+
+
+/** 
+ * @brief 
+ */
+class Atom : public Term
+{
+  private:
+
+    std::string name_;
+
+  public:
+
+    Atom(const std::string& name);
+
+    virtual std::string to_str() const override { return name_; }
+
+    virtual bool is_ground() const override { return true; }
+
+    virtual bool is_atomic() const override { return true; }
+
+    virtual bool operator==(const Term& other) const override;
+
+    virtual std::size_t hash() const override;
+
+    virtual std::string name() const { return name_; }
+
+};
+
+
+class Number : public Term
+{
+  private:
+
+    double number_;
+
+  public:
+
+    Number(double number);
+
+    virtual std::string to_str() const override { return std::to_string(number_); }
+
+    virtual bool is_ground() const override { return true; }
+
+    virtual bool is_atomic() const override { return true; }
+
+    virtual bool operator==(const Term& other) const override;
+
+    virtual std::size_t hash() const override;
+
+    bool is_int() const;
+
+    double number() const { return number_; }
+
+};
+
+
+class Variable : public Term
+{
+
+};
+
+
+class TermV : public Term
+{
+  private:
+
+    std::vector<Term> term_v_;
+
+  public:
+
+    TermV(const std::vector<Term>& term_v);
+
+    TermV(std::initializer_list<Term> il);
+
+};
+
+
+class Compound : public Term
+{
+
+};
+
+/** 
+ * @brief Stream operator that conveniently puts a Term printable version into
+ * an output stream.
+ * 
+ * @param os Output stream
+ * @param term Term to be written into the stream
+ * 
+ * @return os after the insertion
+ */
+std::ostream& operator<<(std::ostream& os, const Term& term);
+
+
+} /* end imagine_planner namespace */
+
+namespace std
+{
+
+/** 
+ * @brief hash struct specialized to Term instances, so they can be used in
+ * unordered sets or maps.
+ */
+template<>
+struct hash<imagine_planner::Term>
+{
+  std::size_t operator()(const imagine_planner::Term& term) const;
+};
+
+}
+
+#endif