Please excuse me if I make glaring mistakes below – I'm a software engineer rather than a mathematician or logician, but I'm trying!
My understanding of relational algebra is that relation headings and their body sets are defined in terms of tuples.
My question is basically – could something similarly powerful to relational algebra "fit together" if all that "relations" had is a set of values from an arbitrary domain. Particularly, I'm thinking of sets of "Value Types" in a programming language, which would be immutable and equatable.
I've not seen a reason yet why this wouldn't work, and in terms of building software, it feels like it might be convenient.
So, given that my language has a Set implementation, I can do the following:
extension Set {
func select(_ predicate: (Element) -> Bool) -> Set<Element> {
return Set(filter(predicate))
}
func project<CoDomain>(_ transform: (Element) -> CoDomain) -> Set<CoDomain> {
return Set<CoDomain>(map(transform))
}
}
func *<A, B>(_ a: Set<A>, _ b: Set<B>) -> Set<CrossProduct<A,B>> {
var result = Set<CrossProduct<A,B>>()
a.forEach { (aElement) in
b.forEach({ (bElement) in
result.insert(CrossProduct(aElement, bElement))
})
}
return result
}
struct CrossProduct<A: Hashable & Equatable, B: Hashable & Equatable> {
let a: A
let b: B
init(_ a: A, _ b: B) {
self.a = a
self.b = b
}
}
Set already has operations for intersection, union, difference, etc. The CrossProduct struct here is to address an unfortunate omission in Swift that its raw tuples can't be put in to a Set.
With these, if I've got my data in sets of values, I can start building up queries on it:
struct Customer {
let name: String
let id: Int
}
let customers = Set([Customer(name:"Ben", id:1),
Customer(name:"Sally", id:2),
Customer(name:"Ben", id:3),
Customer(name:"Misa", id:4)])
let names = customers.project($0.name)
Which would result in names being {"Ben", "Sally", "Misa"}.
(The project method here could also be used to perform domain computation on the set members. Given complex numbers, it could rotate, them, for example.)
A struct Order could also be defined, and we could join a set of orders to customers using * followed by select to see the orders particular customers have made.
So … if this direction of thought is doomed to failure and lack of expression for some reason, I'd love to know before I go much further with it!
My suspicion is that this probably ought to work. Because one could define a relation that had a single heading value of any chosen domain. Which seems equivalent to what I'm proposing. But I could be overlooking many problems with this!
It occurs to me that perhaps the advantage of a tuple based relational algebra is not expressive power, but the opposite: perhaps it imposes useful restrictions that ensure some efficiency bound of queries?
Thank you.