4 ms·
> - Higher-kinded types (template template params): it's possible to implement Haskell-style monads etc. in D, if for some reason you felt the need. Because th
by pcwalton 7y ago
> - Higher-kinded types (template template params): it's possible to implement Haskell-style monads etc. in D, if for some reason you felt the need.
Because the templates aren't typed at all. I'm not sure you can call untyped templates "Haskell-style".
- logicchains 7y agoWhile the templates are technically untyped (in the sense that there are no type-classes or traits in D), you can use template constraints to achieve something similar: https://dlang.org/concepts.html https://dlang.org/concepts.html. Essentially you'd write a compile time isMonad predicate that only returned true if certain functions were defined for a type. Even without that, the key thing is it's still possible to implement monads in the C++ style (https://stackoverflow.com/a/2565191/2553416 https://stackoverflow.com/a/2565191/2553416), whereas it's impossible to write code to do the same thing in current Rust. It just gives much worse compiler errors if you use it wrong compared to if the language had built in type-classes / traits.
- pcwalton 7y agoTemplate constraints aren't the same thing as typed generics. The key issue is that typed generics influence the typechecker. For example, you can write "let x = Default::default(); f(x);" and the compiler can determine the type of x from the type of f. Also, there is the "higher" crate for higher-kinded types if you need them, so it is possible to write a monad typeclass in Rust. It's not exactly something you'd want to use, though.
- logicchains 7y ago>For example, you can write "let x = Default::default(); f(x);" and the compiler can determine the type of x from the type of f. That would be less helpful in C++/D because their compilers don't do Hindley-Milner style bidirectional inference, so even if they had typed generics they wouldn't necessarily be able to do that inference. But I suppose that's an argument in favour of Rust, stronger type inference. >It's not exactly something you'd want to use, though. Ergonomic HKT can make writing various kinds of utilities easier. E.g. imagine I want to write a function Singleton that takes a collection C (vector, list, stream...) and an item of type T, and returns C<T>, a collection containing a single instance of that type. I can write that in Haskell, D or C++, but not in Rust. Or perhaps more usefully, a function Fill, that returns a container C containing n items of type T. For Rust it seems I'd need to write a separate implementation of Fill for each container type, I couldn't write one parameterised over any C?
- paavohtl 7y agoYou can do that without HKT, using FromIterator (which is also used by the widely used iterator method "collect"). Here is an implementation: https://play.rust-lang.org/?version=stable&mode=release&edition=2018&gist=9d7ce08d47215f71199557c799de1cff https://play.rust-lang.org/?version=stable&mode=release&edit... Fill is also possible, using the same trait and iterators.
- logicchains 7y agoI stand corrected. Could the same technique also be used to have a struct parameterised by C and T that had a C as a member?
- leshow 7y agoYou can't partially apply type parameters in rust, that is HKT. But traits & associated types in traits get you pretty far.
- awson 7y ago"wouldn't necessarily be able" It goes completely against the most (perhaps) fundamental part of C++ philosophy of overloading functions on argument types.
- tuukkah 7y agoOverloading does not conflict with type inference: it just means that type annotations are sometimes necessary to get down to concrete types for execution. From "f(x)" we can infer that the type of x is one of f's overloaded argument types.