[rust-dev] How to write Generic traits for enums

Aravinda VK hallimanearavind at gmail.com
Tue Jul 22 09:07:18 PDT 2014


Hi Felix,

Thanks a lot for the detailed explanation.


On Tue, Jul 22, 2014 at 7:08 PM, Felix S. Klock II <pnkfelix at mozilla.com>
wrote:

> Aravinda (cc’ing rust-dev)-
>
> It seems like you are trying to program in Rust as if it were a
> dynamically-typed language, or one with runtime-type reflection (i.e. like
> Java).  At least, that is my best guess at where your misunderstanding lies.
>
> All functions in Rust, even generic ones, need to have their types
> resolved at compile-time.  A generic function can have different concrete
> types substituted in for its type parameters at different call-sites, but
> in the end, a particular call-site needs to resolve to a single type at
> compile-time; the type cannot be left for later resolution at program
> runtime.
>
> In a signature like your:
>
>     fn get_value(settings:HashMap<String, MyTypes>, key: &'static str) ->
> T;
>
> the particular instance of `MyTypes` that is returned will depend on which
> `key` is passed in; therefore, the `T` above could only be dynamically
> determined based on the runtime computation.  It inherently cannot be
> resolved at compile-time, and therefore it is not statically typed.
>
> ----
>
> Rust is not alone in offering this kind of generic types; many programming
> languages use a similar logic for determining types at compile time.  It
> just gets fuzzy if one is used to languages that maintain types at runtime
> and do not enforce restrictions like the one I outlined above.
>
> These type systems are often said to offer “parametric polymorphism”; I
> mention that solely to give you some guidance for a term to search for when
> goggling this subject.  (Though I will say up front that a lot of the
> results you get on this topic can be very academic and language
> research-oriented.)
>
> Here is a tutorial that may help you get a handle on the concepts here:
>
>   http://lucacardelli.name/Papers/BasicTypechecking.pdf
>
> (Yes, it is from 1987.  I think that is why it probably one of the better
> descriptions I was able to find quickly: At that time, these ideas were not
> as widely popularized as they were today, so Cardelli took his time
> explaining the notions and assumed little about the audience.)
>
> rust-dev members: If others know of freely available introductions to this
> topic, I’m all ears; I just didn’t see any obvious winners in my searches.
>
> Cheers,
> -Felix
>
>
> On 22 Jul 2014, at 14:24, Aravinda VK <hallimanearavind at gmail.com> wrote:
>
> Sorry for the incomplete mail.
>
> What I wanted is,
> get_value(MyStr("Rust".to_str())) returns String,
> get_value(MyBool(true)) returns bool and,
> get_value(MyInt(100)) returns int
>
> I was trying to store generic value in hashmap, as in the example below,
>
> use std::collections::hashmap::HashMap;
>
> #[deriving(Show)]
> enum MyTypes{
>     MyBool(bool),
>     MyStr(String),
>     MyInt(int)
> }
>
> fn main(){
>     let mut settings:HashMap<String, MyTypes> = HashMap::new();
>
>     settings.insert("port".to_str(), MyInt(8000));
>     settings.insert("name".to_str(), MyStr("Rust".to_str()));
>     settings.insert("enabled".to_str(), MyBool(true));
>
>     println!("{}", settings);
> }
>
> So to get the value out of hashmap, I need a generic function which checks
> the respective type and returns value. Some thing like
>
> fn get_value(settings:HashMap<String, MyTypes>, key: &'static str) -> T{
>     match settings.get(&key) {
>         MyBool(x) => x,
>         MyStr(x) => x,
>         MyInt(x) => x
>     }
> }
>
> But I don't know how to make this work.
>
> Thanks.
>
>
>
> On Tue, Jul 22, 2014 at 4:55 PM, Felix S. Klock II <pnkfelix at mozilla.com>
> wrote:
>
>> Aravinda (cc’ing rust-dev)-
>>
>> You didn’t show us exactly what you had tried to do to get your code to
>> work, nor did you really describe what it is you want here.
>>
>> E.g. you seem to want `get_value(MyBool(true))` to return a boolean, but
>> since `MyBool` belongs to the `MyTypes` enum, that implies that `get_value`
>> when applied to any variant of `MyTypes` (including `MyInt` or `MyStr`)
>> should also return a boolean … does that seem right to you?
>>
>> In any case, I suspect the missing piece of the puzzle for you is that
>> you need to write an `impl` for the type in question.  I.e. something along
>> the lines of:
>>
>> impl MyTypes {
>>     fn render(&self) -> String {
>>         match *self {
>>             MyBool(x) => format!("{:b}", x),
>>             MyStr(ref x) => x.clone(),
>>             MyInt(x) => format!("{:d}", x),
>>         }
>>     }
>> }
>>
>> (except revised from an Impl for the type to being an impl of some trait
>> for the type).
>>
>> Here is a link to a playpen with your code, and with a couple of example
>> `impl`s for enums (like the one above) tossed in, including an impl of one
>> instance of your `Value<S>` trait.
>>
>>   http://is.gd/RofN9R
>>
>> There is more discussion of writing implementations that also provides an
>> example with a simpler enum) in the Rust tutorial, see:
>>
>>   http://doc.rust-lang.org/tutorial.html#methods
>>
>> Cheers,
>> -Felix
>>
>> On 22 Jul 2014, at 11:45, Aravinda VK <hallimanearavind at gmail.com> wrote:
>>
>> > Hi,
>> >
>> > I am trying to create a generic function to return value depending on
>> the enum passed. But I don't know to create a generic trait for enum.
>> >
>> > In following example, print_value works but I don't know how I can
>> write a generic get_value function to get value from enum.
>> >
>> > #[deriving(Show)]
>> > enum MyTypes{
>> >     MyBool(bool),
>> >     MyStr(String),
>> >     MyInt(int)
>> > }
>> >
>> > fn print_value(arg: MyTypes){
>> >     match arg{
>> >         MyBool(x) => println!("Bool: {}", x),
>> >         MyStr(x) => println!("String: {}", x),
>> >         MyInt(x) => println!("Int: {}", x),
>> >     }
>> > }
>> >
>> >
>> > fn main(){
>> >     print_value(MyBool(true));
>> >
>> >     // Following lines not working, how to write get_value func?
>> >     // let a: bool = get_value(MyBool(true));
>> >     // println!("{}", a);
>> > }
>> >
>> >
>> > In case of struct it is simple,
>> >
>> > struct MyInt {
>> >     value: int
>> > }
>> >
>> > struct MyBool{
>> >     value: bool
>> > }
>> >
>> > trait Value<S>{
>> >     fn get(&self) -> S;
>> > }
>> >
>> > impl Value<int> for MyInt{
>> >     fn get(&self) -> int{
>> >         self.value
>> >     }
>> > }
>> >
>> > impl Value<bool> for MyBool{
>> >     fn get(&self) -> bool{
>> >         self.value
>> >     }
>> > }
>> >
>> > fn get_value<S, T: Value<S>>(arg: T) -> S{
>> >     arg.get()
>> > }
>> >
>> > fn main(){
>> >     let a: bool = get_value(MyBool{value: true});
>> >     println!("{}", a);
>> >
>> >     let b: int = get_value(MyInt{value: 100});
>> >     println!("{}", b);
>> > }
>> >
>> > Please help in writing generic function for enum.
>> >
>> >
>> >
>> > --
>> > Regards
>> > Aravinda | ಅರವಿಂದ
>> > http://aravindavk.in
>> > _______________________________________________
>> > Rust-dev mailing list
>> > Rust-dev at mozilla.org
>> > https://mail.mozilla.org/listinfo/rust-dev
>>
>>
>
>
> --
> Regards
> Aravinda | ಅರವಿಂದ
> http://aravindavk.in
>
>
>


-- 
Regards
Aravinda | ಅರವಿಂದ
http://aravindavk.in
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/rust-dev/attachments/20140722/0dc9e9df/attachment.html>


More information about the Rust-dev mailing list