Mojo, being a systems-level language, has a restriction that most dependently-typed languages don’t, that all type evaluation has to happen before the program can run. This might make it more accurate to call the type system “a weird cousin of dependent types”. If you were to write code in the parameter domain, for instance a DependentBool[value: Bool]
type, you should be able to write the example you proposed once some more type system work is done to handle type refinement. It’s important to note that Mojo’s type system is still a work in progress, so it is more limited than it is planned to be, and that catching up to Rust as far as affine type capabilities are concerned (impl
/extension
, where
/requires
, etc) is likely going to take priority over some of the more exotic capabilities of dependent types since people know what those capabilities are and know both that they want them and how to use them.
There isn’t a lot of information about dependent types in Mojo because all most people care about is “better than Rust”. Feel free to ask more questions since a lot of the other language nerds in the community (and at Modular) like to discuss some of the more theoretical aspects of the language. For the most part, all of us have to yield to the practical side and say that dependent types are in service to making the language faster or safer, which means that since the example you have of being able to manipulate the return type of a function using an if statement can be accomplished using function overloading (1), it’s lower priority to make if statements in that position work, since right now there isn’t a unifying type between String and Int in the language since we don’t expose the “type type” in the language yet. This means that the ternary expression, which requires that both brances be the same type, blows up.
There will be ways to, at fairly substantial performance cost, “lift” a runtime type to the parameter domain, but it’s effectively a large switch statement with cases for each value of the type. Unlike other languages with dependent types, it is somewhat accurate to say that Mojo’s will “stop working” once you are done compiling, since Mojo cannot afford the performance penalties that Lean and other “true dependent” languages accept in exchange for that capability. However, if you evaluate that function at compile time instead, yes it should be doable to have that capability. For the most part, I would expect Lean-like capabilities for things which can be fully evaluated at compile time, since we have an interpreter there similar to what Lean has, and things which depend on runtime data will have restricted capabilities. For Sigma and Pi types in particular, I don’t know enough type theory to speak to that, so I’ll tag in @sora .
Yes, Mojo is lacking proper sum types. Everyone working on the language is VERY aware of a desire for this thanks to Rust showing the programming community at large how useful they are. We have Optional
, which stores a boolean tag, and Variant
, which is a poor man’s sum type that works fine so long as you don’t need 2 names for the same type (ex: 2 named integers). If you need that, you’ll need to newtype so it’s a set of types again.
As for how to implement that extra function in Mojo, you can’t because Mojo will require you to actually build the infinite length List
. If you’re fine with a lazy construct then the same tricks as Scala uses, where you capture a closure to generate the nth member of the list or a generator that yields members, will work.