 	}
 
 	public static func calculatedArticleID(feedID: String, uniqueID: String) -> String {
-		
 		return databaseIDWithString("\(feedID) \(uniqueID)")
+	}
+
+	// MARK: - Hashable
+
+	public func hash(into hasher: inout Hasher) {
+		hasher.combine(articleID)
 	}
 }
 
 public extension Set where Element == Article {
 	
 	public func articleIDs() -> Set<String> {
-		
 		return Set<String>(map { $0.articleID })
 	}
 
 	public func unreadArticles() -> Set<Article> {
-
 		let articles = self.filter { !$0.status.read }
 		return Set(articles)
 	}


public extension Array where Element == Article {
	
	public func articleIDs() -> [String] {
		
		return map { $0.articleID }
	}
}

	public let authors: Set<Author>?
	public let attachments: Set<Attachment>?
	public let status: ArticleStatus

	public init(accountID: String, articleID: String?, feedID: String, uniqueID: String, title: String?, contentHTML: String?, contentText: String?, url: String?, externalURL: String?, summary: String?, imageURL: String?, bannerImageURL: String?, datePublished: Date?, dateModified: Date?, authors: Set<Author>?, attachments: Set<Attachment>?, status: ArticleStatus) {
		
		self.accountID = accountID
