Open jerry73204 opened 4 years ago
These are great observations. I like the idea of allowing direct impl
blocks.
I've been thinking about how to implement higher-order operators like map
. This isn't the same, but I think related to implementing polymorphic operators. For example, TIf. Right now I just hackily monomorphize the trait for a set of known types. But ideally you could do something like
tyrade! {
#[derive(TIf, TMap)]
enum TList {
Nil,
Cons(Type, TList)
}
fn AddOne(N: Num) -> Num { N + 1 }
fn LAddOne(L: List) -> List { TMap(L, AddOne) }
}
@willcrichton You can look at how it is done here.
The crucial part is that whenever we pass something callable to generic places of a type operator, the callable thing must be a type. The Func
trait delegates the type-level computation to a type.
Apart from that, using types that implement Func
maybe an alternative building blocks than using trait + impl blocks. I tried it once and got stuck in the issue that the compiler failed to expand recursive traits. You can see the old compiler issue rust-lang/rust#64917.
I noticed tyrade treats the first argument specially when translating function arguments.
The design does not distinguish functions and methods. For example, users would add
L
name prefixes on list operating traits for distinction. It results in C-style naming.I have an alternative approach that enables us to write methods in
impl {}
block. We can instead move the first argument to the generic list. The additional benefic is that we can define constant-valued functions.While for methods, the
self
is regarded as operands.We can make it further. The
Compute*
traits are generalized into maps like that is done in my type-freak (code). It enables the function passing arguments. For example,List::map
.