Index: libcfa/src/enum.cfa
===================================================================
--- libcfa/src/enum.cfa	(revision 164a6b69daa51bfd2f862b62de3798901ce84825)
+++ libcfa/src/enum.cfa	(revision c333ed2955945a8e97424f193052311ca6b4131f)
@@ -0,0 +1,23 @@
+#include "enum.hfa"
+#include "fstream.hfa"
+
+forall(E, T| TypedEnum(E, T)) {
+    // constructors
+
+    // comparison
+    int ?==?(E l, E r) { return posE(l) == posE(r); }
+    int ?!=?(E l, E r) { return !(l == r); }
+    int ?!=?(E l, zero_t) { return !( posE(l) == 0 ); }
+    int ?<?(E l, E r) { return posE(l) < posE(r); }
+    int ?<=?(E l, E r) { return posE(l) <= posE(r); }
+    int ?>?(E l, E r) { return posE(l) > posE(r); }
+    int ?>=?(E l, E r) {  return posE(l) >= posE(r); }
+
+    // for testing; To be removed
+    // #include <string.h>
+    char * typeEnumString(E e) {
+        // char* out = malloc(sizeof(char) * (5 + strlen(labelE(e) + 1)));
+        // return strcat(strcat(out, "Enum "), labelE(e));
+        return labelE(e);
+    }
+}
Index: libcfa/src/enum.hfa
===================================================================
--- libcfa/src/enum.hfa	(revision 164a6b69daa51bfd2f862b62de3798901ce84825)
+++ libcfa/src/enum.hfa	(revision c333ed2955945a8e97424f193052311ca6b4131f)
@@ -6,5 +6,5 @@
 };
 
-forall(E | Bounded(E)) trait Serial {
+forall(E, T| Bounded(E)) trait Serial {
     unsigned fromInstance(E e);
     E fromInt(unsigned i);
@@ -13,8 +13,12 @@
 };
 
-forall(E, T) trait TypedEnum {
-    T valueE(E e);
+// Opague Enum + TypedEnum
+forall(E, T | Serial(E, T)) trait CfaEnum { 
     char * labelE(E e);
     unsigned int posE(E e);
+};
+
+forall(E, T | CfaEnum(E, T)) trait TypedEnum {
+    T valueE(E e);
 };
 
@@ -28,3 +32,6 @@
     int ?>?(E l, E r);
     int ?>=?(E l, E r);
+
+    // for testing; To be removed
+    char * typeEnumString(E e);
 }
Index: src/ResolvExpr/CandidateFinder.cpp
===================================================================
--- src/ResolvExpr/CandidateFinder.cpp	(revision 164a6b69daa51bfd2f862b62de3798901ce84825)
+++ src/ResolvExpr/CandidateFinder.cpp	(revision c333ed2955945a8e97424f193052311ca6b4131f)
@@ -2138,20 +2138,4 @@
 }
 
-// get the valueE(...) ApplicationExpr that returns the enum value
-const ast::Expr * getValueEnumCall(
-	const ast::Expr * expr,
-	const ResolvExpr::ResolveContext & context, const ast::TypeEnvironment & env ) {
-		auto callExpr = new ast::UntypedExpr(
-			expr->location, new ast::NameExpr( expr->location, "valueE"), {expr} );
-		CandidateFinder finder( context, env );
-		finder.find( callExpr );
-		CandidateList winners = findMinCost( finder.candidates );
-		if (winners.size() != 1) {
-			SemanticError( callExpr, "Ambiguous expression in valueE..." );
-		}
-		CandidateRef & choice = winners.front();
-		return choice->expr;
-}
-
 const ast::Expr * createCondExpr( const ast::Expr * expr ) {
 	assert( expr );
Index: src/ResolvExpr/CandidateFinder.hpp
===================================================================
--- src/ResolvExpr/CandidateFinder.hpp	(revision 164a6b69daa51bfd2f862b62de3798901ce84825)
+++ src/ResolvExpr/CandidateFinder.hpp	(revision c333ed2955945a8e97424f193052311ca6b4131f)
@@ -70,8 +70,4 @@
 	const ast::Expr * expr, Cost & cost );
 
-/// Get the valueE application that returns the enum's value.
-const ast::Expr * getValueEnumCall( const ast::Expr * expr,
-	const ResolveContext & context, const ast::TypeEnvironment & env );
-
 /// Wrap an expression to convert the result to a conditional result.
 const ast::Expr * createCondExpr( const ast::Expr * expr );
Index: src/ResolvExpr/CastCost.cc
===================================================================
--- src/ResolvExpr/CastCost.cc	(revision 164a6b69daa51bfd2f862b62de3798901ce84825)
+++ src/ResolvExpr/CastCost.cc	(revision c333ed2955945a8e97424f193052311ca6b4131f)
@@ -54,7 +54,7 @@
 				cost = conversionCost( basicType, dst, srcIsLvalue, symtab, env );
 				if ( Cost::unsafe < cost ) {
-					if (auto enumInst =  dynamic_cast<const ast::EnumInstType *>(dst)) {
-						assert(enumInst->base->base);
-						cost = Cost::unsafe;
+					if (auto enumInst = dynamic_cast<const ast::EnumInstType *>(dst)) {
+						// Always explict cast only for typed enum
+						if (enumInst->base->isTyped) cost = Cost::unsafe;
 					}
 				}
@@ -63,33 +63,19 @@
 
 		void postvisit( const ast::ZeroType * zero ) {
-			// auto ptr = dynamic_cast< const ast::PointerType * >( dst );
-			// if ( ptr && basicType->isInteger() ) {
-			// 	// needed for, e.g. unsigned long => void *
-			// 	cost = Cost::unsafe;
-			// } else {
 			cost = conversionCost( zero, dst, srcIsLvalue, symtab, env );
 			if ( Cost::unsafe < cost ) {
 				if (auto enumInst =  dynamic_cast<const ast::EnumInstType *>(dst)) {
-					assert(enumInst->base->base);
-					cost = Cost::unsafe;
+					if (enumInst->base->isTyped) cost = Cost::unsafe;
 				}
 			}
-			// }
 		}
 
 		void postvisit( const ast::OneType * one ) {
-			// auto ptr = dynamic_cast< const ast::PointerType * >( dst );
-			// if ( ptr && basicType->isInteger() ) {
-			// 	// needed for, e.g. unsigned long => void *
-			// 	cost = Cost::unsafe;
-			// } else {
 			cost = conversionCost( one, dst, srcIsLvalue, symtab, env );
 			if ( Cost::unsafe < cost ) {
-				if (auto enumInst =  dynamic_cast<const ast::EnumInstType *>(dst)) {
-					assert(enumInst->base->base);
-					cost = Cost::unsafe;
+				if (auto enumInst = dynamic_cast<const ast::EnumInstType *>(dst)) {
+					if (enumInst->base->isTyped) cost = Cost::unsafe;
 				}
 			}
-			// }
 		}
 
Index: src/ResolvExpr/CommonType.cc
===================================================================
--- src/ResolvExpr/CommonType.cc	(revision 164a6b69daa51bfd2f862b62de3798901ce84825)
+++ src/ResolvExpr/CommonType.cc	(revision c333ed2955945a8e97424f193052311ca6b4131f)
@@ -650,5 +650,5 @@
 
 	void postvisit( const ast::EnumInstType * enumInst ) {
-		if ( enumInst->base && !enumInst->base->base ) {
+		if ( enumInst->base && !enumInst->base->isTyped ) {
 			auto basicType = new ast::BasicType( ast::BasicKind::UnsignedInt );
 			result = commonType( basicType, type2, tenv, need, have, open, widen);
Index: src/ResolvExpr/ConversionCost.cc
===================================================================
--- src/ResolvExpr/ConversionCost.cc	(revision 164a6b69daa51bfd2f862b62de3798901ce84825)
+++ src/ResolvExpr/ConversionCost.cc	(revision c333ed2955945a8e97424f193052311ca6b4131f)
@@ -283,5 +283,5 @@
 		cost = costCalc( basicType, integer, srcIsLvalue, symtab, env );
 	} else if ( auto dstAsEnumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) {
-		if ( dstAsEnumInst->base && !dstAsEnumInst->base->base ) {
+		if ( dstAsEnumInst->base && !dstAsEnumInst->base->isTyped ) {
 			cost = Cost::unsafe;
 		}
@@ -480,5 +480,5 @@
 		// assuming 0p is supposed to be used for pointers?
 	} else if ( auto dstAsEnumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) {
-		if ( dstAsEnumInst->base && !dstAsEnumInst->base->base ) {
+		if ( dstAsEnumInst->base && !dstAsEnumInst->base->isTyped ) {
 			cost = Cost::unsafe;
 		}
@@ -501,5 +501,5 @@
 		}
 	} else if ( auto dstAsEnumInst = dynamic_cast< const ast::EnumInstType * >( dst ) ) {
-		if ( dstAsEnumInst->base && !dstAsEnumInst->base->base ) {
+		if ( dstAsEnumInst->base && !dstAsEnumInst->base->isTyped ) {
 			cost = Cost::unsafe;
 		}
Index: src/Validate/ImplementEnumFunc.cpp
===================================================================
--- src/Validate/ImplementEnumFunc.cpp	(revision 164a6b69daa51bfd2f862b62de3798901ce84825)
+++ src/Validate/ImplementEnumFunc.cpp	(revision c333ed2955945a8e97424f193052311ca6b4131f)
@@ -28,37 +28,4 @@
 		  proto_linkage{ast::Linkage::Cforall} {}
 
-	void genAttrFunctions();
-	void genSuccPredPosn();
-	// void genSuccPredDecl();
-
-	void appendReturnThis(ast::FunctionDecl* decl) {
-		assert(1 <= decl->params.size());
-		assert(1 == decl->returns.size());
-		assert(decl->stmts);
-
-		const CodeLocation& location = (decl->stmts->kids.empty())
-		                                   ? decl->stmts->location
-		                                   : decl->stmts->kids.back()->location;
-		const ast::DeclWithType* thisParam = decl->params.front();
-		decl->stmts.get_and_mutate()->push_back(new ast::ReturnStmt(
-			location, new ast::VariableExpr(location, thisParam)));
-	}
-	void genAttrStandardFuncs() {
-		ast::FunctionDecl* (EnumAttrFuncGenerator::*standardProtos[4])()
-			const = {&EnumAttrFuncGenerator::genCtorProto,
-					 &EnumAttrFuncGenerator::genCopyProto,
-					 &EnumAttrFuncGenerator::genDtorProto,
-					 &EnumAttrFuncGenerator::genAssignProto};
-		for (auto& generator : standardProtos) {
-			ast::FunctionDecl* decl = (this->*generator)();
-			produceForwardDecl(decl);
-			genFuncBody(decl);
-			if (CodeGen::isAssignment(decl->name)) {
-				appendReturnThis(decl);
-			}
-			produceDecl(decl);
-		}
-	}
-
 private:
 	const CodeLocation& getLocation() const { return decl->location; }
@@ -73,31 +40,29 @@
 	const ast::Decl* getDecl() const { return decl; }
 
-	// Implement Bounded trait for enum
-    void genBoundedFunctions();
-	// Implement Serial trait for enum
+	// Implement Bounded trait
+	void genBoundedFunctions();
+	ast::FunctionDecl* genBoundedProto(const char *) const;
+	void genBoundedBody(ast::FunctionDecl* func) const;
+
+	// Implement Serial trait
 	void genSerialTraitFuncs();
-
-	// Bounded trait
-	ast::FunctionDecl* genLowerBoundProto() const;
-	ast::FunctionDecl* genUpperBoundProto() const;
-	void genLowerBoundBody(ast::FunctionDecl* func) const;
-	void genUpperBoundBody(ast::FunctionDecl* func) const;
-
+	ast::FunctionDecl* genFromIntProto() const;
+	ast::FunctionDecl* genFromInstanceProto() const;
+	ast::FunctionDecl* genInstToInstFuncProto(const char* func) const;
+	void genFromIntBody(ast::FunctionDecl *) const; 
+	void genFromInstanceBody(ast::FunctionDecl *) const;
+	void genSuccPredBody(ast::FunctionDecl *, const char *) const;
+
+	// Implement TypedEnum trait
+	void genTypedEnumFuncs();
+	void genTypedEnumFunction(const ast::EnumAttribute attr);
 	ast::FunctionDecl* genPosnProto() const;
 	ast::FunctionDecl* genLabelProto() const;
 	ast::FunctionDecl* genValueProto() const;
-
-	// Serial trait
-	ast::FunctionDecl* genFromIntProto() const;
-	ast::FunctionDecl* genFromInstanceProto() const;
-	ast::FunctionDecl* genSuccProto() const;
-	ast::FunctionDecl* genPredProto() const;
-
-	void genFromIntBody(ast::FunctionDecl *) const; 
-	void genFromInstanceBody(ast::FunctionDecl *) const;
+	void genValueOrLabelBody(
+		ast::FunctionDecl* func, ast::ObjectDecl* arrDecl) const;
+	void genPosnBody(ast::FunctionDecl* func) const;
+
 	////////////////
-
-	ast::FunctionDecl* genSuccPosProto() const;
-	ast::FunctionDecl* genPredPosProto() const;
 
 	// ---------------------------------------------------
@@ -121,88 +86,5 @@
 	}
 
-	/// E = EnumAttrType<T>`
-	/// `void ?{}(E & _dst)`.
-	ast::FunctionDecl* genCtorProto() const {
-		return genProto("?{}", {dstParam()}, {});
-	}
-
-	/// void ?{}(E & _dst, E _src)`.
-	ast::FunctionDecl* genCopyProto() const {
-		return genProto("?{}", {dstParam(), srcParam()}, {});
-	}
-
-	///`void ^?{}(E & _dst)`.
-	ast::FunctionDecl* genDtorProto() const {
-		// The destructor must be mutex on a concurrent type.
-		return genProto("^?{}", {dstParam()}, {});
-	}
-
-	/// `E ?{}(E & _dst, E _src)`.
-	ast::FunctionDecl* genAssignProto() const {
-		// Only the name is different, so just reuse the generation function.
-		auto retval = srcParam();
-		retval->name = "_ret";
-		return genProto("?=?", {dstParam(), srcParam()}, {retval});
-	}
-
-	void genFuncBody(ast::FunctionDecl* func) {
-		const CodeLocation& location = func->location;
-		auto& params = func->params;
-		if (InitTweak::isCopyConstructor(func) ||
-			InitTweak::isAssignment(func)) {
-			assert(2 == params.size());
-			auto dstParam = params.front().strict_as<ast::ObjectDecl>();
-			auto srcParam = params.back().strict_as<ast::ObjectDecl>();
-			func->stmts = genCopyBody(location, dstParam, srcParam);
-		} else {
-			assert(1 == params.size());
-			// Default constructor and destructor is empty.
-			func->stmts = new ast::CompoundStmt(location);
-			// Add unused attribute to parameter to silence warnings.
-			addUnusedAttribute(params.front());
-
-			// Just an extra step to make the forward and declaration match.
-			if (forwards.empty()) return;
-			ast::FunctionDecl* fwd = strict_dynamic_cast<ast::FunctionDecl*>(
-				forwards.back().get_and_mutate());
-			addUnusedAttribute(fwd->params.front());
-		}
-	}
-
-	const ast::CompoundStmt* genCopyBody( const CodeLocation& location,
-			const ast::ObjectDecl* dstParam, const ast::ObjectDecl* srcParam) {
-		return new ast::CompoundStmt(
-			location,
-			{new ast::ExprStmt(
-				location,
-				new ast::UntypedExpr(
-					location, new ast::NameExpr(location, "__builtin_memcpy"),
-					{
-						new ast::AddressExpr( location,
-							new ast::VariableExpr( location, dstParam ) ),
-						new ast::AddressExpr( location,
-							new ast::VariableExpr( location, srcParam ) ),
-						new ast::SizeofExpr( location, srcParam->type ),
-					}))});
-	}
-
-	void genDtorBody(ast::FunctionDecl* func) {
-		const CodeLocation& location = func->location;
-		auto& params = func->params;
-		assert(1 == params.size());
-		func->stmts = new ast::CompoundStmt(location);
-		addUnusedAttribute(params.front());
-
-		// Just an extra step to make the forward and declaration match.
-		if (forwards.empty()) return;
-		ast::FunctionDecl* fwd = strict_dynamic_cast<ast::FunctionDecl*>(
-			forwards.back().get_and_mutate());
-		addUnusedAttribute(fwd->params.front());
-	}
-
-	// ast::FunctionDecl*
 	// ----------------------------------------------------
-
-	ast::FunctionDecl* genSuccPredFunc(bool succ);
 
 	const ast::Init* getAutoInit(const ast::Init* prev) const;
@@ -214,8 +96,4 @@
 		const ast::EnumAttribute attr, const CodeLocation& location,
 		std::vector<ast::ptr<ast::Init>>& inits) const;
-	void genValueOrLabelBody(
-		ast::FunctionDecl* func, ast::ObjectDecl* arrDecl) const;
-	void genPosnBody(ast::FunctionDecl* func) const;
-	void genAttributesDecls(const ast::EnumAttribute attr);
 };
 
@@ -374,24 +252,53 @@
 }
 
+void EnumAttrFuncGenerator::genSuccPredBody(ast::FunctionDecl * func, const char* opt) const {
+	auto params = func->params;
+	assert( params.size() == 1 );
+	auto param = params.front();
+	auto enumToInt = new ast::CastExpr(
+		func->location,
+		new ast::VariableExpr(func->location, param),
+		new ast::BasicType(ast::BasicKind::UnsignedInt),
+		ast::GeneratedFlag::ExplicitCast
+	);
+	ast::UntypedExpr* addOneExpr = ast::UntypedExpr::createCall( func->location,
+		opt,
+		{enumToInt,
+		ast::ConstantExpr::from_int(func->location, 1)}
+	);
+	auto intToEnum = new ast::CastExpr(
+		func->location,
+		addOneExpr,
+		new ast::EnumInstType( decl ),
+		ast::GeneratedFlag::ExplicitCast
+	);
+	func->stmts = new ast::CompoundStmt(
+		func->location, {
+			new ast::ReturnStmt(
+				func->location,
+				intToEnum
+			)
+		}
+	);
+}
+
+
 void EnumAttrFuncGenerator::genSerialTraitFuncs() {
-	auto fromIntProto = genFromIntProto();
-	produceForwardDecl(fromIntProto);
-	genFromIntBody(fromIntProto);
-	produceDecl(fromIntProto);
-
-	auto fromInstanceProto = genFromInstanceProto();
-	produceForwardDecl(fromInstanceProto);
-	genFromInstanceBody(fromInstanceProto);
-	produceDecl(fromInstanceProto);
-
-	auto succProto = genSuccProto();
-	auto predProto = genPredProto();
-	produceForwardDecl(succProto);
-	produceForwardDecl(predProto);
-}
-
-ast::FunctionDecl* EnumAttrFuncGenerator::genSuccProto() const {
+	ast::FunctionDecl * protos[4] = {
+		genFromIntProto(),
+		genFromInstanceProto(),
+		genInstToInstFuncProto("succ"),
+		genInstToInstFuncProto("pred")
+	};
+	for (auto& proto: protos) produceForwardDecl(proto);
+	genFromIntBody(protos[0]);
+	genFromInstanceBody(protos[1]);
+	genSuccPredBody(protos[2], "?+?");
+	genSuccPredBody(protos[3], "?-?");
+}
+
+ast::FunctionDecl* EnumAttrFuncGenerator::genInstToInstFuncProto(const char * func) const {
 	return genProto(
-		"succ",
+		func,
 		{new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
 		{new ast::ObjectDecl(getLocation(), "_ret",
@@ -399,71 +306,28 @@
 }
 
-ast::FunctionDecl* EnumAttrFuncGenerator::genPredProto() const {
-	return genProto(
-		"pred",
-		{new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))},
-		{new ast::ObjectDecl(getLocation(), "_ret",
-		                     new ast::EnumInstType(decl))});
-}
-
-ast::FunctionDecl* EnumAttrFuncGenerator::genLowerBoundProto() const {
-    return genProto("lowerBound", {}, {
+ast::FunctionDecl* EnumAttrFuncGenerator::genBoundedProto(const char * func) const {
+    return genProto(func, {}, {
         new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))
     });
 }
 
-ast::FunctionDecl* EnumAttrFuncGenerator::genUpperBoundProto() const {
-    return genProto("upperBound", {}, {
-        new ast::ObjectDecl(getLocation(), "_i", new ast::EnumInstType(decl))
-    });
-}
-
-void EnumAttrFuncGenerator::genLowerBoundBody(ast::FunctionDecl* func) const {
+void EnumAttrFuncGenerator::genBoundedBody(ast::FunctionDecl* func) const {
 	const CodeLocation & loc = func->location;
-	auto mem = decl->members.front();
-	// auto expr = new ast::QualifiedNameExpr( loc, decl, mem->name );
-	// expr->result = new ast::EnumInstType( decl );
+	auto mem = func->name=="lowerBound"?  decl->members.front() : decl->members.back();
 	auto expr = new ast::NameExpr( loc, mem->name );
 	func->stmts = new ast::CompoundStmt( loc, {new ast::ReturnStmt(loc, expr)});
 }
 
-void EnumAttrFuncGenerator::genUpperBoundBody(ast::FunctionDecl* func) const {
-	const CodeLocation & loc = func->location;
-	auto mem = decl->members.back();
-	auto expr = new ast::NameExpr( loc, mem->name );
-	// expr->result = new ast::EnumInstType( decl );
-	func->stmts = new ast::CompoundStmt( loc, {new ast::ReturnStmt(loc, expr)});	
-}
-
 void EnumAttrFuncGenerator::genBoundedFunctions() {
-	ast::FunctionDecl * upperDecl = genUpperBoundProto();
-	produceForwardDecl(upperDecl);
-	genUpperBoundBody(upperDecl);
-	produceDecl(upperDecl);
-
-	ast::FunctionDecl * lowerDecl = genLowerBoundProto();
-	produceForwardDecl(lowerDecl);
-	genLowerBoundBody(lowerDecl);
-	produceDecl(lowerDecl);
+	ast::FunctionDecl * boundedProtos[2] = {genBoundedProto("upperBound"), genBoundedProto("lowerBound")};
+	for (auto & protos: boundedProtos) {
+		produceForwardDecl(protos);
+		genBoundedBody(protos);
+		produceDecl(protos);
+	}
 }
 
 inline ast::EnumAttrType * getPosnType( const ast::EnumDecl * decl ) {
 	return new ast::EnumAttrType(new ast::EnumInstType(decl), ast::EnumAttribute::Posn);
-}
-
-ast::FunctionDecl* EnumAttrFuncGenerator::genSuccPosProto() const {
-	return genProto(
-		"_successor_",
-		{new ast::ObjectDecl(getLocation(), "_i", getPosnType(decl))},
-		{new ast::ObjectDecl(getLocation(), "_ret", getPosnType(decl))}
-	);
-}
-
-ast::FunctionDecl* EnumAttrFuncGenerator::genPredPosProto() const {
-	return genProto(
-		"_predessor_",
-		{new ast::ObjectDecl(getLocation(), "_i", getPosnType(decl))},
-		{new ast::ObjectDecl(getLocation(), "_ret", getPosnType(decl))}
-	);
 }
 
@@ -511,7 +375,8 @@
 }
 
-void EnumAttrFuncGenerator::genAttributesDecls(const ast::EnumAttribute attr) {
+void EnumAttrFuncGenerator::genTypedEnumFunction(const ast::EnumAttribute attr) {
 	if (attr == ast::EnumAttribute::Value ||
 		attr == ast::EnumAttribute::Label) {
+		// TypedEnum's backing arrays
 		std::vector<ast::ptr<ast::Init>> inits =
 			attr == ast::EnumAttribute::Value ? genValueInit() : genLabelInit();
@@ -534,58 +399,8 @@
 }
 
-ast::FunctionDecl* EnumAttrFuncGenerator::genSuccPredFunc(bool succ) {
-	ast::FunctionDecl* funcDecl = succ ? genSuccPosProto() : genPredPosProto();
-	produceForwardDecl(funcDecl);
-
-	const CodeLocation& location = getLocation();
-
-	auto& params = funcDecl->params;
-	assert(params.size() == 1);
-	auto param = params.front().strict_as<ast::ObjectDecl>();
-
-
-	auto rets = funcDecl->returns;
-	assert(params.size() == 1);
-	auto ret = rets.front().strict_as<ast::ObjectDecl>();
-	auto retType = ret->type.strict_as<ast::EnumAttrType>();
-
-	auto addOneExpr = ast::UntypedExpr::createCall( location,
-		succ? "?+?": "?-?",
-		{new ast::VariableExpr(location, param),
-		ast::ConstantExpr::from_int(location, 1)}
-	);
-
-	funcDecl->stmts = new ast::CompoundStmt(
-		location, {
-			new ast::ReturnStmt(
-				location,
-				new ast::CastExpr(location, addOneExpr, retType)
-			)
-		}
-	);
-
-	return funcDecl;
-}
-
-void EnumAttrFuncGenerator::genAttrFunctions() {
-	genAttributesDecls(ast::EnumAttribute::Value);
-	genAttributesDecls(ast::EnumAttribute::Label);
-	genAttributesDecls(ast::EnumAttribute::Posn);	
-}
-
-// void EnumAttrFuncGenerator::genSuccPredDecl() {
-// 	auto succProto = genSuccProto();
-// 	auto predProto = genPredProto();
-
-// 	produceForwardDecl(succProto);
-// 	produceForwardDecl(predProto);
-// }
-
-void EnumAttrFuncGenerator::genSuccPredPosn() {
-	ast::FunctionDecl* succ = genSuccPredFunc(true);
-	ast::FunctionDecl* pred = genSuccPredFunc(false);
-
-	produceDecl(succ);
-	produceDecl(pred);
+void EnumAttrFuncGenerator::genTypedEnumFuncs() {
+	if (decl->base) genTypedEnumFunction(ast::EnumAttribute::Value);
+	genTypedEnumFunction(ast::EnumAttribute::Label);
+	genTypedEnumFunction(ast::EnumAttribute::Posn);	
 }
 
@@ -593,9 +408,6 @@
 	std::list<ast::ptr<ast::Decl>>& decls) {
 	// Generate the functions (they go into forwards and definitions).
-	genAttrStandardFuncs();
-	genAttrFunctions();
+	genTypedEnumFuncs();
 	genSerialTraitFuncs();
-	genSuccPredPosn();
-	// problematic
 	genBoundedFunctions();
 	// Now export the lists contents.
@@ -618,10 +430,7 @@
 
 void ImplementEnumFunc::previsit(const ast::EnumDecl* enumDecl) {
-	if (!enumDecl->body) return;
-	if (!enumDecl->base) return;
-
+	if (!enumDecl->body || !enumDecl->isTyped) return;
 	ast::EnumInstType enumInst(enumDecl->name);
 	enumInst.base = enumDecl;
-
 	EnumAttrFuncGenerator gen(enumDecl, &enumInst, functionNesting);
 	gen.generateAndAppendFunctions(declsToAddAfter);
Index: c/Validate/ReplacePseudoFunc.cpp
===================================================================
--- src/Validate/ReplacePseudoFunc.cpp	(revision 164a6b69daa51bfd2f862b62de3798901ce84825)
+++ 	(revision )
@@ -1,72 +1,0 @@
-#include "ReplacePseudoFunc.hpp"
-
-#include <set>
-
-#include "AST/Decl.hpp"
-#include "AST/Inspect.hpp"
-#include "AST/Pass.hpp"
-#include "AST/Print.hpp"
-#include "AST/Stmt.hpp"
-#include "Common/utility.h"
-#include "ResolvExpr/CandidateFinder.hpp"
-#include "ResolvExpr/Resolver.h"
-#include "SymTab/Mangler.h"
-
-namespace Validate {
-
-namespace {
-
-ast::ptr<ast::Expr> reduceCastExpr(ast::ptr<ast::Expr> expr) {
-    if (auto castExpr = expr.as<ast::CastExpr>()) {
-        return reduceCastExpr(castExpr->arg);
-    }
-    return expr;
-}
-
-struct ReplaceSuccAndPred final : public ast::WithSymbolTable,
-                                  public ast::WithConstTranslationUnit {
-    const ast::Expr* postvisit(const ast::ApplicationExpr* expr) {
-        auto fname = ast::getFunctionName(expr);
-        if (fname == "succ" || fname == "pred") {
-            const CodeLocation& location = expr->location;
-            if (expr->args.size() != 1) return expr;
-
-            auto param = expr->args.front();
-            if (auto argAsVar = reduceCastExpr(param).as<ast::VariableExpr>()) {
-                if (auto argAsDecl = argAsVar->var.as<ast::ObjectDecl>()) {
-                    if (auto enumInst =
-                            argAsDecl->type.as<ast::EnumInstType>()) {
-                        auto castTo = new ast::EnumAttrType(
-                            enumInst, ast::EnumAttribute::Posn);
-                        auto castExpr =
-                            new ast::CastExpr(param->location, param, castTo);
-
-                        auto untyped = new ast::UntypedExpr(
-                            expr->location,
-                            new ast::NameExpr(location, fname == "succ"
-                                                            ? "_successor_"
-                                                            : "_predessor_"),
-                            {castExpr});
-                        ResolvExpr::ResolveContext context{symtab,
-                                                           transUnit().global};
-                        auto typedResult =
-                            ResolvExpr::findVoidExpression(untyped, context);
-                        ast::ptr<ast::ApplicationExpr> ret =
-                            typedResult.strict_as<ast::ApplicationExpr>();
-                        return ast::deepCopy(ret);
-                    } else if (argAsDecl->type.as<ast::EnumAttrType>()) {
-                        std::cerr << "PseudoFunc: succ/pred should not be applied on EnumAttrType directly" << std::endl;
-                    }
-                }
-            }
-        }
-        return expr;
-    }
-};
-
-}  // namespace
-
-void replacePseudoFunc(ast::TranslationUnit& translationUnit) {
-    ast::Pass<ReplaceSuccAndPred>::run(translationUnit);
-}
-}  // namespace Validate
Index: src/Validate/module.mk
===================================================================
--- src/Validate/module.mk	(revision 164a6b69daa51bfd2f862b62de3798901ce84825)
+++ src/Validate/module.mk	(revision c333ed2955945a8e97424f193052311ca6b4131f)
@@ -53,6 +53,4 @@
 	Validate/VerifyCtorDtorAssign.cpp \
 	Validate/VerifyCtorDtorAssign.hpp \
-	Validate/ReplacePseudoFunc.cpp \
-	Validate/ReplacePseudoFunc.hpp \
 	Validate/ImplementEnumFunc.cpp \
 	Validate/ImplementEnumFunc.hpp
Index: src/main.cc
===================================================================
--- src/main.cc	(revision 164a6b69daa51bfd2f862b62de3798901ce84825)
+++ src/main.cc	(revision c333ed2955945a8e97424f193052311ca6b4131f)
@@ -83,5 +83,4 @@
 #include "Validate/ReturnCheck.hpp"         // for checkReturnStatements
 #include "Validate/VerifyCtorDtorAssign.hpp" // for verifyCtorDtorAssign
-#include "Validate/ReplacePseudoFunc.hpp"   // for replacePseudoFunc
 #include "Virtual/ExpandCasts.h"            // for expandCasts
 #include "Virtual/VirtualDtor.hpp"          // for implementVirtDtors
@@ -383,5 +382,4 @@
 		PASS( "Resolve", ResolvExpr::resolve, transUnit );
 		DUMP( exprp, std::move( transUnit ) );
-		PASS( "Replace Pseudo Func", Validate::replacePseudoFunc, transUnit );
 		PASS( "Fix Init", InitTweak::fix, transUnit, buildingLibrary() ); // Here
 		PASS( "Erase With", ResolvExpr::eraseWith, transUnit );
Index: tests/enum_tests/.expect/voidEnum.txt
===================================================================
--- tests/enum_tests/.expect/voidEnum.txt	(revision 164a6b69daa51bfd2f862b62de3798901ce84825)
+++ tests/enum_tests/.expect/voidEnum.txt	(revision c333ed2955945a8e97424f193052311ca6b4131f)
@@ -1,3 +1,7 @@
-Not Equal
+Two different Opague Enum Should not be the same:
+a and b are Not Equal
+Default Output:
 0
 1
+a
+b
Index: tests/enum_tests/structEnum.cfa
===================================================================
--- tests/enum_tests/structEnum.cfa	(revision 164a6b69daa51bfd2f862b62de3798901ce84825)
+++ tests/enum_tests/structEnum.cfa	(revision c333ed2955945a8e97424f193052311ca6b4131f)
@@ -17,7 +17,7 @@
 };
 
-// PointEnum foo(PointEnum in) {
-//      return in;
-// }
+PointEnum identity(PointEnum in) {
+     return in;
+}
 
 // The only valid usage
