[rust-dev] Safely writing iterators over idiomatic C structures

2013-12-06 Thread Edward Z . Yang
Imagine that we have a structure of the form:

typedef struct {
int payload1;
foo *link;
int payload2;
} foo;

This structure is characterized by two things:

1) It is a singly linked list, and thus has a simple ownership
structure which can be captured by Rust's owned pointers

2) The payload of this struct is interleaved with links, in
order to save space and an extra indirection.  The layout may
be fixed, by virtue of being exposed by a C library.

The question now is: can we write an Iteratormut foo for
the corresponding Rust structure foo, without using any unsafe code?

There is a fundamental problem with this structure: iterator
invalidation.  If we are able to issue a mut foo reference, then the
link field could get mutated.  Rust's borrow checker would reject this,
since the only possible internal state for the iterator (a mutable
reference to the next element) aliases with the mutable reference
returned by next().  I am not sure how to solve this without changing
the layout of the struct; perhaps there might be a way if one could
selectively turn off the mutability of some fields.

Suppose we are willing to change the struct, as per the extra::dlist
implementation, we still fall short of a safe implementation: the
internal state of the iterator utilizes a raw pointer (head), which
provides a function resolve() which simply mints a mutable reference to
the element in question. It seems to be using Rawlink to hide the fact
that it has its fingers on a mutable borrowed reference to the list.  It
recovers some safety by maintaining a mutable reference to the whole
list in the iterator structure as well, but it would be better if no
unsafe code was necessary at all, and I certainly don't feel qualified
to reason about the correctness of this code. (Though, I understand and
appreciate the fact that the back pointers have to be handled unsafely.)

So, is it possible? I just want (provably) safe, mutable iteration over
singly-linked lists...

Edward
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Safely writing iterators over idiomatic C structures

2013-12-06 Thread Huon Wilson

On 06/12/13 19:11, Edward Z. Yang wrote:

Imagine that we have a structure of the form:

 typedef struct {
 int payload1;
 foo *link;
 int payload2;
 } foo;

This structure is characterized by two things:

 1) It is a singly linked list, and thus has a simple ownership
 structure which can be captured by Rust's owned pointers

 2) The payload of this struct is interleaved with links, in
 order to save space and an extra indirection.  The layout may
 be fixed, by virtue of being exposed by a C library.

The question now is: can we write an Iteratormut foo for
the corresponding Rust structure foo, without using any unsafe code?

There is a fundamental problem with this structure: iterator
invalidation.  If we are able to issue a mut foo reference, then the
link field could get mutated.  Rust's borrow checker would reject this,
since the only possible internal state for the iterator (a mutable
reference to the next element) aliases with the mutable reference
returned by next().  I am not sure how to solve this without changing
the layout of the struct; perhaps there might be a way if one could
selectively turn off the mutability of some fields.

Suppose we are willing to change the struct, as per the extra::dlist
implementation, we still fall short of a safe implementation: the
internal state of the iterator utilizes a raw pointer (head), which
provides a function resolve() which simply mints a mutable reference to
the element in question. It seems to be using Rawlink to hide the fact
that it has its fingers on a mutable borrowed reference to the list.  It
recovers some safety by maintaining a mutable reference to the whole
list in the iterator structure as well, but it would be better if no
unsafe code was necessary at all, and I certainly don't feel qualified
to reason about the correctness of this code. (Though, I understand and
appreciate the fact that the back pointers have to be handled unsafely.)

So, is it possible? I just want (provably) safe, mutable iteration over
singly-linked lists...

Edward
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


One could have an Iterator(mut int, mut int), where the references 
point to just the fields. Off the top of my head:


struct List {
payload1: int,
next: Option~Foo,
payload2: f64
}

struct ListMutIterator'a {
elem: Option'a mut List
}

impl'a Iterator('a mut int, 'a mut f64) for ListMutIterator'a {
fn next(mut self) - Option('a mut int, 'a mut f64) {
 let elem = std::util::replace(self, None); // I think this 
might be necessary to get around the borrow checker.


 let (ret, next) = match elem {
 Some(List { payload1: ref mut payload1, next: ref mut 
next, payload2: ref mut payload2 }) = {

  (Some((payload1, payload2)), next.as_mut_ref())
 }
 None = (None, None)
 };
 *self = next;
 ret
}
}

(The List pattern match will look nicer if 
https://github.com/mozilla/rust/issues/6137 gets solved; `List { ref mut 
payload1, ref mut next, ref mut payload2 }`.)


I imagine this will end up being very ugly if there are more than just 2 
fields before and after, although one could easily replace the tuple 
with a struct `ListMutRef'a { payload1: 'a mut int, payload2: 'a mut 
f64 }`.


Huon
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Safely writing iterators over idiomatic C structures

2013-12-06 Thread Bill Myers
Maybe the language should be changed to allow Iterator to be changed to have a 
signature like this:
pub trait IteratorA {
    fn next'a('a mut self) - Option'a A;
}

Then you could return the mut by reborrowing and would be able to advance the 
iterator without issue afterwards. 
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


[rust-dev] Let’s avoid having both foo() and foo_opt()

2013-12-06 Thread Simon Sapin
We have some functions and methods such as 
[std::str::from_utf8](http://static.rust-lang.org/doc/master/std/str/fn.from_utf8.html) 
that may succeed and give a result, or fail when the input is invalid.


1. Sometimes we assume the input is valid and don’t want to deal with 
the error case. Task failure works nicely.


2. Sometimes we do want to do something different on invalid input, so 
returning an `OptionT` works best.


And so we end up with both `from_utf8` and `from_utf8`. This particular 
case is worse because we also have `from_utf8_owned` and 
`from_utf8_owned_opt`, to cover everything.


Multiplying names like this is just not good design. I’d like to reduce 
this pattern.


Getting behavior 1. when you have 2. is easy: just call `.unwrap()` on 
the Option. I think we should rename every `foo_opt()` function or 
method to just `foo`, remove the old `foo()` behavior, and tell people 
(through documentation) to use `foo().unwrap()` if they want it back?


The downsides are that unwrap is more verbose and gives less helpful 
error messages on task failure. But I think it’s worth it.


What do you think?

(PS: I’m guilty of making this worse in #10828, but I’d like to discuss 
this before sending pull requests with invasive API changes.)


--
Simon Sapin
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Let’s avoid having both foo() and foo_opt()

2013-12-06 Thread Corey Richardson
I'm in favor of this but it makes things less pretty. Is the choice
really between pretty and fast?

On Fri, Dec 6, 2013 at 3:41 PM, Simon Sapin simon.sa...@exyr.org wrote:
 We have some functions and methods such as
 [std::str::from_utf8](http://static.rust-lang.org/doc/master/std/str/fn.from_utf8.html)
 that may succeed and give a result, or fail when the input is invalid.

 1. Sometimes we assume the input is valid and don’t want to deal with the
 error case. Task failure works nicely.

 2. Sometimes we do want to do something different on invalid input, so
 returning an `OptionT` works best.

 And so we end up with both `from_utf8` and `from_utf8`. This particular case
 is worse because we also have `from_utf8_owned` and `from_utf8_owned_opt`,
 to cover everything.

 Multiplying names like this is just not good design. I’d like to reduce this
 pattern.

 Getting behavior 1. when you have 2. is easy: just call `.unwrap()` on the
 Option. I think we should rename every `foo_opt()` function or method to
 just `foo`, remove the old `foo()` behavior, and tell people (through
 documentation) to use `foo().unwrap()` if they want it back?

 The downsides are that unwrap is more verbose and gives less helpful error
 messages on task failure. But I think it’s worth it.

 What do you think?

 (PS: I’m guilty of making this worse in #10828, but I’d like to discuss this
 before sending pull requests with invasive API changes.)

 --
 Simon Sapin
 ___
 Rust-dev mailing list
 Rust-dev@mozilla.org
 https://mail.mozilla.org/listinfo/rust-dev
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Safely writing iterators over idiomatic C structures

2013-12-06 Thread Edward Z . Yang
OK, with a little bit of tweaking I have come up with a version
that seems to work:

struct List {
payload1: int,
next: Option~List,
payload2: f64
}

struct ListMutIterator'a {
elem: Option'a mut List
}

impl'a Iterator('a mut int, 'a mut f64) for ListMutIterator'a {
fn next(mut self) - Option('a mut int, 'a mut f64) {
let elem = std::util::replace(self, ListMutIterator{elem:None}); // 
I think this might be necessary to get around the borrow checker.

let (ret, next) = match elem {
ListMutIterator{elem: Some(List { payload1: ref mut payload1, 
next: ref mut next, payload2: ref mut payload2 })} = {
 (Some((payload1, payload2)), match *next {
None = None,
 Some(ref mut p) = Some(mut **p)
 })
}
ListMutIterator{elem: None} = (None, None)
};
*self = ListMutIterator{elem:next};
ret
}
}

Perhaps dlist should be updated to use this implementation strategy?

Edward
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Safely writing iterators over idiomatic C structures

2013-12-06 Thread Edward Z . Yang
Excerpts from Huon Wilson's message of 2013-12-06 00:26:36 -0800:
 One could have an Iterator(mut int, mut int), where the references 
 point to just the fields. Off the top of my head:

Sure. (This is not so good when there are a lot of fields.)

  impl'a Iterator('a mut int, 'a mut f64) for ListMutIterator'a {
  fn next(mut self) - Option('a mut int, 'a mut f64) {
   let elem = std::util::replace(self, None); // I think this 
 might be necessary to get around the borrow checker.
 
   let (ret, next) = match elem {
   Some(List { payload1: ref mut payload1, next: ref mut 
 next, payload2: ref mut payload2 }) = {
(Some((payload1, payload2)), next.as_mut_ref())

I fixed some of the egregious type-checking errors, but this one has me
stuck.  There is no as_mut_ref() in the version of Rust I'm running, and
the plausible replacement mut_ref() doesn't do what I want:

Huon.rs|24 col 37 error| mismatched types: expected 
`std::option::Optionmut List` but found `std::option::Optionmut ~List` 
(expected struct List but found ~-ptr)

(Because, of course, the thing inside the option is a ~List, not a
List).

Cheers,
Edward
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Let’s avoid having both foo() and foo_opt()

2013-12-06 Thread Daniel Micay
On Fri, Dec 6, 2013 at 3:41 PM, Simon Sapin simon.sa...@exyr.org wrote:
 We have some functions and methods such as
 [std::str::from_utf8](http://static.rust-lang.org/doc/master/std/str/fn.from_utf8.html)
 that may succeed and give a result, or fail when the input is invalid.

 1. Sometimes we assume the input is valid and don’t want to deal with the
 error case. Task failure works nicely.

 2. Sometimes we do want to do something different on invalid input, so
 returning an `OptionT` works best.

 And so we end up with both `from_utf8` and `from_utf8`. This particular case
 is worse because we also have `from_utf8_owned` and `from_utf8_owned_opt`,
 to cover everything.

 Multiplying names like this is just not good design. I’d like to reduce this
 pattern.

 Getting behavior 1. when you have 2. is easy: just call `.unwrap()` on the
 Option. I think we should rename every `foo_opt()` function or method to
 just `foo`, remove the old `foo()` behavior, and tell people (through
 documentation) to use `foo().unwrap()` if they want it back?

 The downsides are that unwrap is more verbose and gives less helpful error
 messages on task failure. But I think it’s worth it.

 What do you think?

 (PS: I’m guilty of making this worse in #10828, but I’d like to discuss this
 before sending pull requests with invasive API changes.)

 --
 Simon Sapin

A stack trace already tells you where the error came from so I don't
think it's an important consideration. Rust can provide stack traces
on failure by default if that's desired.
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Let’s avoid having both foo() and foo_opt()

2013-12-06 Thread Brian Anderson

On 12/06/2013 12:41 PM, Simon Sapin wrote:
We have some functions and methods such as 
[std::str::from_utf8](http://static.rust-lang.org/doc/master/std/str/fn.from_utf8.html) 
that may succeed and give a result, or fail when the input is invalid.


1. Sometimes we assume the input is valid and don’t want to deal with 
the error case. Task failure works nicely.


2. Sometimes we do want to do something different on invalid input, so 
returning an `OptionT` works best.


And so we end up with both `from_utf8` and `from_utf8`. This 
particular case is worse because we also have `from_utf8_owned` and 
`from_utf8_owned_opt`, to cover everything.


Multiplying names like this is just not good design. I’d like to 
reduce this pattern.


Getting behavior 1. when you have 2. is easy: just call `.unwrap()` on 
the Option. I think we should rename every `foo_opt()` function or 
method to just `foo`, remove the old `foo()` behavior, and tell people 
(through documentation) to use `foo().unwrap()` if they want it back?


The downsides are that unwrap is more verbose and gives less helpful 
error messages on task failure. But I think it’s worth it.


What do you think?

(PS: I’m guilty of making this worse in #10828, but I’d like to 
discuss this before sending pull requests with invasive API changes.)




I agree in this case (and probably a lot of cases), especially since 
this is a relatively uncommon operation and since (I think) we're 
prefering 'get' to 'unwrap' and that's even shorter.


There are some cases where I think failure is the right option by 
default though; in particular I was worried you were going to bring up 
the 'send' and 'recv' methods on channels which fail when disconnected. 
In this case I think it won't be common to handle the failure since it 
indicates some logic error, and these are very common operations.


___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Let’s avoid having both foo() and foo_opt()

2013-12-06 Thread Simon Sapin

On 06/12/2013 20:48, Corey Richardson wrote:

I'm in favor of this but it makes things less pretty. Is the choice
really between pretty and fast?


I don’t think this is about speed. My concern is that having two 
almost-identical names for functions that do almost the same thing is 
not a good design, and should be avoided if possible.


--
Simon Sapin
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Let’s avoid having both foo() and foo_opt()

2013-12-06 Thread Simon Sapin

On 06/12/2013 20:55, Léo Testard wrote:

Hi,

Just a suggestion, don't know what it's worth...

For the not helpful error message thing, couldn't we extend the
option API, to be able to specify at the creation of a None value
the error string that will be displayed if one calls unwrap() on this
value ? This may be useful in several situations.


That would require making the memory representation of every Option 
bigger. Just for the (hopefully) uncommon case of task failure, it’s not 
worth the cost in my opinion.


We could instead have .unwrap() that take an error message, but that 
leaves the responsibility to the user of the API.


--
Simon Sapin
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Let’s avoid having both foo() and foo_opt()

2013-12-06 Thread Eric Reed
FYI, there's already a method on Option that is unwrap() with an error
message: expect().

Personally, I prefer making functions that don't fail and use Option or
Result and then composing them with functions that fail for certain
outputs, but I think I'm in the minority there.


On Fri, Dec 6, 2013 at 1:45 PM, Simon Sapin simon.sa...@exyr.org wrote:

 On 06/12/2013 20:55, Léo Testard wrote:

 Hi,

 Just a suggestion, don't know what it's worth...

 For the not helpful error message thing, couldn't we extend the
 option API, to be able to specify at the creation of a None value
 the error string that will be displayed if one calls unwrap() on this
 value ? This may be useful in several situations.


 That would require making the memory representation of every Option
 bigger. Just for the (hopefully) uncommon case of task failure, it’s not
 worth the cost in my opinion.

 We could instead have .unwrap() that take an error message, but that
 leaves the responsibility to the user of the API.


 --
 Simon Sapin
 ___
 Rust-dev mailing list
 Rust-dev@mozilla.org
 https://mail.mozilla.org/listinfo/rust-dev

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Let’s avoid having both foo() and foo_opt()

2013-12-06 Thread Simon Sapin

On 06/12/2013 21:44, Brian Anderson wrote:

I agree in this case (and probably a lot of cases), especially since
this is a relatively uncommon operation and since (I think) we're
prefering 'get' to 'unwrap' and that's even shorter.

There are some cases where I think failure is the right option by
default though; in particular I was worried you were going to bring up
the 'send' and 'recv' methods on channels which fail when disconnected.
In this case I think it won't be common to handle the failure since it
indicates some logic error, and these are very common operations.



Maybe this should be a case-by-case decision, but send/try_send and 
recv/try_recv have the same issue as from_utf8/from_utf8_opt of two 
slightly different names for almost the same thing.


--
Simon Sapin
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Let’s avoid having both foo() and foo_opt()

2013-12-06 Thread Simon Sapin

On 06/12/2013 21:50, Eric Reed wrote:

Personally, I prefer making functions that don't fail and use Option or
Result and then composing them with functions that fail for certain
outputs, but I think I'm in the minority there.


Yes, this is what I’m suggesting.

--
Simon Sapin
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Let’s avoid having both foo() and foo_opt()

2013-12-06 Thread Palmer Cox
Why not use Result instead of Option for these types of things? Result is
already defined to be able to return error codes using Err. The only way to
indicate an error when returning an Option is to return None which doesn't
allow for that. Also, IMO, None doesn't necessarily mean error to me.
Lets say we have a function defined as:

fn do_something(value: Option~str);

It seems like it would be much to easy to accidentally write something
like: do_something(str::from_utf8(...)) which might result in the error
being hidden since do_something might not consider None to be an error
input.

-Palmer Cox



On Fri, Dec 6, 2013 at 4:52 PM, Simon Sapin simon.sa...@exyr.org wrote:

 On 06/12/2013 21:50, Eric Reed wrote:

 Personally, I prefer making functions that don't fail and use Option or
 Result and then composing them with functions that fail for certain
 outputs, but I think I'm in the minority there.


 Yes, this is what I’m suggesting.


 --
 Simon Sapin
 ___
 Rust-dev mailing list
 Rust-dev@mozilla.org
 https://mail.mozilla.org/listinfo/rust-dev

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Let’s avoid having both foo() and foo_opt()

2013-12-06 Thread Gaetan
I also find the repeatition of unwrap all over the code being quite nasty

Most of the time the result is just unwrapped without taking into account
the error case, so i think the usage of Option or Result useless.

I think a good solution exits and can make the code more maintainable, and
easier to read. There should not have all these unwrap (or get) call for
code we know it cannot fails, because the necessary check has been done
earlier.

I am in favor of two version of the api: from_str which has already done
the unwrap, and a from_str_safe for instance that returns a Result or
option.

Or perhaps allow the propagation of Option/Result.
Le 7 déc. 2013 01:03, Daniel Micay danielmi...@gmail.com a écrit :

 On Fri, Dec 6, 2013 at 7:00 PM, Palmer Cox palmer...@gmail.com wrote:
  Why not use Result instead of Option for these types of things? Result is
  already defined to be able to return error codes using Err. The only way
 to
  indicate an error when returning an Option is to return None which
 doesn't
  allow for that. Also, IMO, None doesn't necessarily mean error to me.
 Lets
  say we have a function defined as:
 
  fn do_something(value: Option~str);
 
  It seems like it would be much to easy to accidentally write something
 like:
  do_something(str::from_utf8(...)) which might result in the error being
  hidden since do_something might not consider None to be an error input.
 
  -Palmer Cox

 If there's only one reason it could fail, then `Option` is the
 idiomatic way to report the error case. It's exactly what `Option` is
 used for. A stack trace can report where the error occurred if you
 decide to ignore the error case and use `unwrap` (or `get`, if it's
 renamed).
 ___
 Rust-dev mailing list
 Rust-dev@mozilla.org
 https://mail.mozilla.org/listinfo/rust-dev

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Let’s avoid having both foo() and foo_opt()

2013-12-06 Thread Gaetan
Isnt a way for Option to unwrap implicitely when check on error state is
not done ? That would make the code less verbose but still allow the dev to
check for error if want?
Le 7 déc. 2013 01:12, Gaetan gae...@xeberon.net a écrit :

 I also find the repeatition of unwrap all over the code being quite nasty

 Most of the time the result is just unwrapped without taking into account
 the error case, so i think the usage of Option or Result useless.

 I think a good solution exits and can make the code more maintainable, and
 easier to read. There should not have all these unwrap (or get) call for
 code we know it cannot fails, because the necessary check has been done
 earlier.

 I am in favor of two version of the api: from_str which has already done
 the unwrap, and a from_str_safe for instance that returns a Result or
 option.

 Or perhaps allow the propagation of Option/Result.
 Le 7 déc. 2013 01:03, Daniel Micay danielmi...@gmail.com a écrit :

 On Fri, Dec 6, 2013 at 7:00 PM, Palmer Cox palmer...@gmail.com wrote:
  Why not use Result instead of Option for these types of things? Result
 is
  already defined to be able to return error codes using Err. The only
 way to
  indicate an error when returning an Option is to return None which
 doesn't
  allow for that. Also, IMO, None doesn't necessarily mean error to me.
 Lets
  say we have a function defined as:
 
  fn do_something(value: Option~str);
 
  It seems like it would be much to easy to accidentally write something
 like:
  do_something(str::from_utf8(...)) which might result in the error being
  hidden since do_something might not consider None to be an error input.
 
  -Palmer Cox

 If there's only one reason it could fail, then `Option` is the
 idiomatic way to report the error case. It's exactly what `Option` is
 used for. A stack trace can report where the error occurred if you
 decide to ignore the error case and use `unwrap` (or `get`, if it's
 renamed).
 ___
 Rust-dev mailing list
 Rust-dev@mozilla.org
 https://mail.mozilla.org/listinfo/rust-dev


___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Let’s avoid having both foo() and foo_opt()

2013-12-06 Thread Simon Sapin

On 07/12/2013 00:12, Gaetan wrote:

I am in favor of two version of the api: from_str which has already done
the unwrap, and a from_str_safe for instance that returns a Result or
option.


This is what we have now. (Eg. from_utf8() and from_utf8_opt())

The point of my initial email was to argue against this. I think we 
should try to avoid doubling the amount of API.




Or perhaps allow the propagation of Option/Result.


This is why we have methods like .map() and .and_then()

--
Simon Sapin
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Let’s avoid having both foo() and foo_opt()

2013-12-06 Thread spir

On 12/06/2013 09:41 PM, Simon Sapin wrote:

We have some functions and methods such as
[std::str::from_utf8](http://static.rust-lang.org/doc/master/std/str/fn.from_utf8.html)
that may succeed and give a result, or fail when the input is invalid.

1. Sometimes we assume the input is valid and don’t want to deal with the error
case. Task failure works nicely.

2. Sometimes we do want to do something different on invalid input, so returning
an `OptionT` works best.

And so we end up with both `from_utf8` and `from_utf8`. This particular case is
worse because we also have `from_utf8_owned` and `from_utf8_owned_opt`, to cover
everything.

Multiplying names like this is just not good design. I’d like to reduce this
pattern.

Getting behavior 1. when you have 2. is easy: just call `.unwrap()` on the
Option. I think we should rename every `foo_opt()` function or method to just
`foo`, remove the old `foo()` behavior, and tell people (through documentation)
to use `foo().unwrap()` if they want it back?

The downsides are that unwrap is more verbose and gives less helpful error
messages on task failure. But I think it’s worth it.

What do you think?

(PS: I’m guilty of making this worse in #10828, but I’d like to discuss this
before sending pull requests with invasive API changes.)


[A bit long, sorry, this is a topic about which i have thought for a while.]

There may be a more complicated general pattern, of all kinds of functions that 
may not be able to perform their nominal task, due to invalid input, but the 
client cannot know whether the input is valid without more or less reproducing 
said task. Checking utf8 validity is about the same job as decoding, for 
instance, to reuse your example.


Compare with a function computing the average value of a collection of numbers 
(or the sum, product, std-dev, etc...) which is passed an empty collection: here 
the client can know, thus:
1. if this abnormal case does not belong to the app's logic, the client should 
just call the func stupidly so that the func failure is a signal of logical 
error on the app side
2. if instead this case belongs to the app's logic, the client should first 
check, and never call the func in this special case
Thus, despite very possible failure, there should here be only one version of 
the func (no *_opt), one that stupidly fails, with a stupid error msg.


Back to the cases where the client cannot know before calling. To this category 
belong a whole series of search/find functions, and many dealing with the file 
system, user input, input in general. In the latter case, a func's input is in 
fact not (all) provided by the client. But there is the same pattern of 
anomalous cases which may, or not, belong to the app logic (1. or 2. above): is 
it correct (if special or exceptional) that such file does not exist, or such 
collection does not hold the searched item? Meaning, should I deal with such 
cases? If not, if such a case does not belong to the application logic, again I 
should stupidly call a func that stupidly fails with a stupid error msg, so I am 
told, simply and early, of my logical errors. These are true errors (not 
so-called exceptions), and the failure is a symptom or signal, a good thing (if, 
indeed, what you want is making good software). I *want* it; and want it so!


I'm in favor of simple funcs doing simple tasks simply, and just failing in 
anomalous cases, for these reasons. [1]


Remains the situation combined of such funcs, of which the client cannot know 
whether they will be able to perform their task, and of abnormal cases belonging 
to the logic of the app (there are also whole categories of maintenance and 
safety modes here). For such situations, it looks somewhat logical to have 2 
versions, I guess. Playing a bit with words:
1. when I ask to _find_ something, I take it for granted the thing is somewhere 
there, and expect a location in return
2. when I ask to _search_ something, I do not take anything for granted, and 
expect in return _either_ not there! or a location
This duality applies both to the so-called real world (despite blur natural 
language word meanings) and software worlds, and extends to all cases, it seems. 
We can certainly find a way, using Option or another mean, to combine both 
categories of situations (1. or 2.) using a single tool, but this should be very 
well done, and ensure that:
* In cases of category 1., developers are warned about their errors exactly as 
if they had called a stupidly failing func.
* At the semantic (conceptual) level, the duality of categories remains somehow 
preserved, including in source code.
About the latter, in particular it should be obvious in code, without knowledge 
of language arcanes or weird idioms, that (or whether) the caller expects a 
success unconditionally -- because (and in other words that) the anomalous case 
just does not belong to this app; this is critical information to the reader. 
How to do that right?


PS: I take the 

Re: [rust-dev] Let’s avoid having both foo() and foo_opt()

2013-12-06 Thread Simon Sapin

On 07/12/2013 00:49, spir wrote:

About the latter, in particular it should be obvious in code, without knowledge
of language arcanes or weird idioms, that (or whether) the caller expects a
success unconditionally -- because (and in other words that) the anomalous case
just does not belong to this app; this is critical information to the reader.
How to do that right?


If my proposal is accepted (returning Option is favored), then calling 
.unwrap() is the way to express that success is expected. unwrap() 
causes task failure when called with None.


--
Simon Sapin
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Let’s avoid having both foo() and foo_opt()

2013-12-06 Thread spir

On 12/07/2013 01:12 AM, Gaetan wrote:

I am in favor of two version of the api: from_str which has already done
the unwrap, and a from_str_safe for instance that returns a Result or
option.


This provides the important semantic information (that I've evoked at the end 
end of a long earlier reply in this thread) of whether func failure is expected 
and belongs to the logic of the present app and we must deal with it, or not.


But I'm still shared on this topic for finding it also annoying, like Simon, to 
have to duplicate whole catogories of such funcs (of which we cannot know in 
advance whther they'll fail or not), if only the interface as apparently 
proposed by Gaëtan.


Denis
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Let’s avoid having both foo() and foo_opt()

2013-12-06 Thread spir

On 12/07/2013 01:55 AM, Simon Sapin wrote:

On 07/12/2013 00:49, spir wrote:

About the latter, in particular it should be obvious in code, without knowledge
of language arcanes or weird idioms, that (or whether) the caller expects a
success unconditionally -- because (and in other words that) the anomalous case
just does not belong to this app; this is critical information to the reader.
How to do that right?


If my proposal is accepted (returning Option is favored), then calling .unwrap()
is the way to express that success is expected. unwrap() causes task failure
when called with None.


Maybe it's only me, but this not at at all clear to my eyes. My imagined soluton 
(for a totally different lang) was something like this, on the caller side:


ucodes = s.utf8_decode()!   // source should be correct, error on 
failure
ucodes = s.utf8_decode()?	// logical failure expected, return None or 
whatnot


(But maybe _this_ is obscure to your eyes?)

Denis
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Let’s avoid having both foo() and foo_opt()

2013-12-06 Thread Jordi Boggiano
On Sat, Dec 7, 2013 at 2:01 AM, spir denis.s...@gmail.com wrote:
 On 12/07/2013 01:12 AM, Gaetan wrote:

 I am in favor of two version of the api: from_str which has already done
 the unwrap, and a from_str_safe for instance that returns a Result or
 option.

 This provides the important semantic information (that I've evoked at the
 end end of a long earlier reply in this thread) of whether func failure is
 expected and belongs to the logic of the present app and we must deal with
 it, or not.

 But I'm still shared on this topic for finding it also annoying, like Simon,
 to have to duplicate whole catogories of such funcs (of which we cannot know
 in advance whther they'll fail or not), if only the interface as apparently
 proposed by Gaëtan.

Syntax sugar like this would be nice:

let str = std::str::from_utf8(Parse this optimistically, and fail otherwise);
// str is a string or the task fails

vs.

let opt_str = std::str::from_utf?(Parse this if valid); // note the
question mark
if opt_str.is_some() {  }

Problem is, this sounds scary to implement at the compiler level, if
it's possible at all :) I am just throwing it out there for others to
judge.

Cheers

-- 
Jordi Boggiano
@seldaek - http://nelm.io/jordi
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Let’s avoid having both foo() and foo_opt()

2013-12-06 Thread Huon Wilson

On 07/12/13 12:08, Jordi Boggiano wrote:

On Sat, Dec 7, 2013 at 2:01 AM, spir denis.s...@gmail.com wrote:

On 12/07/2013 01:12 AM, Gaetan wrote:

I am in favor of two version of the api: from_str which has already done
the unwrap, and a from_str_safe for instance that returns a Result or
option.

This provides the important semantic information (that I've evoked at the
end end of a long earlier reply in this thread) of whether func failure is
expected and belongs to the logic of the present app and we must deal with
it, or not.

But I'm still shared on this topic for finding it also annoying, like Simon,
to have to duplicate whole catogories of such funcs (of which we cannot know
in advance whther they'll fail or not), if only the interface as apparently
proposed by Gaëtan.

Syntax sugar like this would be nice:

let str = std::str::from_utf8(Parse this optimistically, and fail otherwise);
// str is a string or the task fails

vs.

let opt_str = std::str::from_utf?(Parse this if valid); // note the
question mark
if opt_str.is_some() {  }

Problem is, this sounds scary to implement at the compiler level, if
it's possible at all :) I am just throwing it out there for others to
judge.

Cheers



I personally think a better solution is something like Haskell's do 
notation[1], where you can chain several computations that return 
Option.. such that if any intermediate one returns None, the later 
ones are not evaluated and the whole expression returns None, which 
saves having to call .get()/.unwrap()/.expect() a lot.


This can work for types like Result too (in fact, the Haskell 
implementation of `do` is sugar around some monad functions, so any 
monad can be used there; we currently don't have the power to express 
the monad typeclass/trait in Rust so the fully general form probably 
isn't possible as a syntax extension yet, although a limited version is).



Huon

[1]: http://en.wikibooks.org/wiki/Haskell/do_Notation

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Let’s avoid having both foo() and foo_opt()

2013-12-06 Thread Jordi Boggiano
On Sat, Dec 7, 2013 at 2:07 AM, spir denis.s...@gmail.com wrote:
 Maybe it's only me, but this not at at all clear to my eyes. My imagined
 soluton (for a totally different lang) was something like this, on the
 caller side:

 ucodes = s.utf8_decode()!   // source should be correct, error
 on failure
 ucodes = s.utf8_decode()?   // logical failure expected, return
 None or whatnot

 (But maybe _this_ is obscure to your eyes?)

Looks like our mails had a race condition on this one, but
highlighting the cases where we expect a perfect world (i.e. !) is
probably better.

However, if you just call the method without anything it would be the
same as calling it with ? suffix as far as I understand, so I'm not
sure what the point is of keeping that one.

Cheers

-- 
Jordi Boggiano
@seldaek - http://nelm.io/jordi
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Let’s avoid having both foo() and foo_opt()

2013-12-06 Thread Liigo Zhuang
Is do-notation in Haskell similar as: try{ block } ?


2013/12/7 Huon Wilson dbau...@gmail.com

 On 07/12/13 12:08, Jordi Boggiano wrote:

 On Sat, Dec 7, 2013 at 2:01 AM, spir denis.s...@gmail.com wrote:

 On 12/07/2013 01:12 AM, Gaetan wrote:

 I am in favor of two version of the api: from_str which has already done
 the unwrap, and a from_str_safe for instance that returns a Result or
 option.

 This provides the important semantic information (that I've evoked at the
 end end of a long earlier reply in this thread) of whether func failure
 is
 expected and belongs to the logic of the present app and we must deal
 with
 it, or not.

 But I'm still shared on this topic for finding it also annoying, like
 Simon,
 to have to duplicate whole catogories of such funcs (of which we cannot
 know
 in advance whther they'll fail or not), if only the interface as
 apparently
 proposed by Gaëtan.

 Syntax sugar like this would be nice:

 let str = std::str::from_utf8(Parse this optimistically, and fail
 otherwise);
 // str is a string or the task fails

 vs.

 let opt_str = std::str::from_utf?(Parse this if valid); // note the
 question mark
 if opt_str.is_some() {  }

 Problem is, this sounds scary to implement at the compiler level, if
 it's possible at all :) I am just throwing it out there for others to
 judge.

 Cheers


 I personally think a better solution is something like Haskell's do
 notation[1], where you can chain several computations that return
 Option.. such that if any intermediate one returns None, the later ones
 are not evaluated and the whole expression returns None, which saves having
 to call .get()/.unwrap()/.expect() a lot.

 This can work for types like Result too (in fact, the Haskell
 implementation of `do` is sugar around some monad functions, so any monad
 can be used there; we currently don't have the power to express the monad
 typeclass/trait in Rust so the fully general form probably isn't possible
 as a syntax extension yet, although a limited version is).


 Huon

 [1]: http://en.wikibooks.org/wiki/Haskell/do_Notation


 ___
 Rust-dev mailing list
 Rust-dev@mozilla.org
 https://mail.mozilla.org/listinfo/rust-dev




-- 
by *Liigo*, http://blog.csdn.net/liigo/
Google+  https://plus.google.com/105597640837742873343/
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Let’s avoid having both foo() and foo_opt()

2013-12-06 Thread Ziad Hatahet
I posted a question on the mailing list concerning this back in May:
https://mail.mozilla.org/pipermail/rust-dev/2013-May/004176.html

There were a couple of responses which implemented this in a macro. It
would be nice if it were at the language level though.


--
Ziad


On Fri, Dec 6, 2013 at 5:14 PM, Huon Wilson dbau...@gmail.com wrote:

 On 07/12/13 12:08, Jordi Boggiano wrote:

 On Sat, Dec 7, 2013 at 2:01 AM, spir denis.s...@gmail.com wrote:

 On 12/07/2013 01:12 AM, Gaetan wrote:

 I am in favor of two version of the api: from_str which has already done
 the unwrap, and a from_str_safe for instance that returns a Result or
 option.

 This provides the important semantic information (that I've evoked at the
 end end of a long earlier reply in this thread) of whether func failure
 is
 expected and belongs to the logic of the present app and we must deal
 with
 it, or not.

 But I'm still shared on this topic for finding it also annoying, like
 Simon,
 to have to duplicate whole catogories of such funcs (of which we cannot
 know
 in advance whther they'll fail or not), if only the interface as
 apparently
 proposed by Gaëtan.

 Syntax sugar like this would be nice:

 let str = std::str::from_utf8(Parse this optimistically, and fail
 otherwise);
 // str is a string or the task fails

 vs.

 let opt_str = std::str::from_utf?(Parse this if valid); // note the
 question mark
 if opt_str.is_some() {  }

 Problem is, this sounds scary to implement at the compiler level, if
 it's possible at all :) I am just throwing it out there for others to
 judge.

 Cheers


 I personally think a better solution is something like Haskell's do
 notation[1], where you can chain several computations that return
 Option.. such that if any intermediate one returns None, the later ones
 are not evaluated and the whole expression returns None, which saves having
 to call .get()/.unwrap()/.expect() a lot.

 This can work for types like Result too (in fact, the Haskell
 implementation of `do` is sugar around some monad functions, so any monad
 can be used there; we currently don't have the power to express the monad
 typeclass/trait in Rust so the fully general form probably isn't possible
 as a syntax extension yet, although a limited version is).


 Huon

 [1]: http://en.wikibooks.org/wiki/Haskell/do_Notation


 ___
 Rust-dev mailing list
 Rust-dev@mozilla.org
 https://mail.mozilla.org/listinfo/rust-dev

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Let’s avoid having both foo() and foo_opt()

2013-12-06 Thread Patrick Walton

On 12/6/13 6:46 PM, Niko Matsakis wrote:

I agree. I've personally been moving towards `ResultT, ()` in
preference to `OptionT` when one of the branches reflects an
error. It's worth noting that the compiler could still optimize this
into a pointer-null-pointer representation, though I doubt it does so
now.


IIRC it does.

Patrick

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Let’s avoid having both foo() and foo_opt()

2013-12-06 Thread Brendan Zabarauskas

On 7 Dec 2013, at 10:47 am, Simon Sapin simon.sa...@exyr.org wrote:

 This is why we have methods like .map() and .and_then()

I like using these higher order functions, but I run into lots of issues with 
moved values because we don’t have once functions. I end up having to use 
matches, which are awfully verbose for simple things. :(

~Brendan
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Let’s avoid having both foo() and foo_opt()

2013-12-06 Thread Oren Ben-Kiki
There was a whole thread about the need for once-stack-closures. They are
really vital for simple programming with higher-order functions such as
these. I'm not optimistic about them being added though :-(


On Sat, Dec 7, 2013 at 8:15 AM, Brendan Zabarauskas bjz...@yahoo.com.auwrote:


 On 7 Dec 2013, at 10:47 am, Simon Sapin simon.sa...@exyr.org wrote:

  This is why we have methods like .map() and .and_then()

 I like using these higher order functions, but I run into lots of issues
 with moved values because we don’t have once functions. I end up having to
 use matches, which are awfully verbose for simple things. :(

 ~Brendan
 ___
 Rust-dev mailing list
 Rust-dev@mozilla.org
 https://mail.mozilla.org/listinfo/rust-dev

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Let’s avoid having both foo() and foo_opt()

2013-12-06 Thread Palmer Cox
Especially if ResultT, () is optimized into a single word, it seems ideal
to me to get rid of str::from_utf_opt([u8]) - Option~str and just have
str::from_utf([u8]) - Result~str, (). This makes simple programs that
don't care about error handling a little more complicated, of course, since
it forces them to handle the error case. Although, the only extra
complication is .unwrap() so, its not that bad. For more complex programs
that do care about error handling it makes it explicit at the call site how
the error condition should be handled which I think is a big win. Return
code checking is a C idiom, and there is nothing wrong with that style of
error handling. However, the C compiler doesn't do much of anything to
force you to check the return codes which leads to lots of code that fails
to do so. Using a Result, however, forces the caller to do those checks.
Result still supports various chaining functions just like Option to
make that easier. However, you don't have to worry about accidentally
passing a None to a function that takes an Option as an input parameter
with non-error semantics.

Also, I like unwrap() since to me, nothing about get() says: this is an
error handling function that might lead to killing the current task. get()
sounds simple and safe, buts its not if called on an Option.

-Palmer Cox


On Fri, Dec 6, 2013 at 11:14 PM, Patrick Walton pcwal...@mozilla.comwrote:

 On 12/6/13 6:46 PM, Niko Matsakis wrote:

 I agree. I've personally been moving towards `ResultT, ()` in
 preference to `OptionT` when one of the branches reflects an
 error. It's worth noting that the compiler could still optimize this
 into a pointer-null-pointer representation, though I doubt it does so
 now.


 IIRC it does.

 Patrick


 ___
 Rust-dev mailing list
 Rust-dev@mozilla.org
 https://mail.mozilla.org/listinfo/rust-dev

___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


[rust-dev] Higher-Kinded Types vs C++ Combos

2013-12-06 Thread David Piepgrass
Rust newb here. I have theoretical questions.

Recently I noticed that Higher-Kinded Types (HKTs) have been mentioned on
the mailing list a lot, but I had no idea what a HKT was, or what it might
be good for. After reading about them a little, they reminded me of C++'s
template template parameters. In C++ you can almost write something like
this:

template template typename class collection
struct Numbers {
   collectionint integers;
   collectionfloat floats;
};

So then you can write Numbersvector for a structure that contains
vectorT collections, and Numberslist for a structure that contains
listT collections. EXCEPT that it doesn't actually work, because
vectorT has two template parameters (the second one, the allocator, is
normally left at its default). Let's ignore that, though.

So that brings me to my first question: is this what higher-kinded types
means? What is the difference, if any, between HKT and C++ template
templates?

However, as a C++ developer I never actually used a template template
parameter because I didn't know they existed for a long time. So instead I
would have written this, which has the same end-result:

struct VectorTrait
{
templatetypename T
struct collection { typedef vectorT type; };
};
struct ListTrait
{
templatetypename T
struct collection { typedef listT type; };
};

templatetypename Traits
struct Numbers
{
Traits::collectionint::type integers;
Traits::collectionfloat::type floats;
};
// Use NumbersVectorTrait for vectorT, NumbersListTrait for listT.

This is clunkier, but it would have been a bit simpler if C++ supported
templatized typedefs:

struct VectorTrait
{
templatetypename T typedef vectorT collection;
};
struct ListTrait
{
templatetypename T typedef vectorT collection;
};

templatetypename Traits
struct Numbers
{
Traits::collectionint integers;
Traits::collectionfloat floats;
};
// Now write NumbersVectorTrait instead of Numbersvector,
//   NumbersListTrait instead of Numberslist.

I have found that because of the existence of typedef, template template
parameters are never actually necessary; so far, I've never seen a
situation where the typedef-based solution wasn't almost as good. Also, I
have found that trait types filled with typedefs seem to be a more
general thing than template template; they allow you to do things that
would be very difficult or impossible without them. For example you can use
typedefs-in-a-struct to create circular references among types that don't
know about each other:

// I call this a Combo; I don't know if the technique has a standard name
struct MyCombo {
typedef ConcreteATraits A;
typedef ConcreteBTraits B;
typedef ConcreteCTraits C;
};
templatetypename Combo
class ConcreteA { Combo::B* b; ... };
templatetypename Combo
class ConcreteB { Combo::C* c; ... };
templatetypename Combo
class ConcreteC { Combo::A* b; ... };

Here I've created a network of types (ConcreteAMyCombo,
ConcreteBMyCombo, and ConcreteCMyCombo) that are linked together
through the Combo type MyCombo, so the types can all use each other, but
none of the types refer to each other directly. This design allows you to
freely swap in different implementations of A, B, and C; it has similar
advantages to dependency injection or inversion of control in languages
like Java and C#, except that the linkages are all defined statically at
compile-time, so no dynamic dispatch is required.

Without the ability to define typedefs, this approach is not possible at
all if there is a cyclic relationship. Also, if the combo declares more
than three types, it becomes impractical to specify all those types on the
classes directly as type parameters.

In C# I learned that this quickly becomes a major problem if you need to
parameterize on more than one or two types. I tried to do generic math
(which requires at least two type parameters due to the under-designed
standard libraries) and I also implemented a GiST data structure (see
http://en.wikipedia.org/wiki/GiST), and found out that the lack of any
analog to C++ typedef makes both of those tasks very clumsy, while also
making the code hard to read, because you end up with a rats' nest of type
parameters (or if you omit (otherwise necessary) type parameters, you might
use lots of casts instead.)

So I guess that leads me to two more questions.

2. Does Rust have a typedef equivalent that can be used in this way?
3. Does it make sense to just suggest just use typedefs instead of
Higher-Kinded Types?
___
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev


Re: [rust-dev] Higher-Kinded Types vs C++ Combos

2013-12-06 Thread Brendan Zabarauskas
Of course this leads (assuming we had a `Collection` trait) to the horrendously 
ugly `Numbers::i32, ~[i32], f32, ~[f32](...)` if you wanted to be explicit. 
But hopefully your code would be such that Rust could infer the bounds. This 
will be alleviated in the future by associated items, but that will probably be 
post 1.0.

(I might be getting a little off-topic here)

~Brendan

On 7 Dec 2013, at 5:27 pm, Brendan Zabarauskas bjz...@yahoo.com.au wrote:

 I’m not sure I understand everything in your post, but this is how I’d write 
 you first C++ example:
 
struct NumbersIV, FV {
priv iv: IV,// priv so the struct can only be constructed in this 
 module
priv fv: FV,
}
 
implI: Int, IV: CollectionI, F: Float, FV: CollectionF NumbersIV, 
 FV {
pub fn new(iv: IV, fv: FV) - NumbersIV, FV {
Numbers { iv: iv, fv: fv }
}
}
 
 You can also write type aliases with type parameters, but I don’t think you 
 can enforce trait bounds on them afaik:
 
   type AT = (T, int);
 
 
 ~Brendan
 
 
 On 7 Dec 2013, at 5:10 pm, David Piepgrass qwertie...@gmail.com wrote:
 
 Rust newb here. I have theoretical questions.
 
 Recently I noticed that Higher-Kinded Types (HKTs) have been mentioned on 
 the mailing list a lot, but I had no idea what a HKT was, or what it might 
 be good for. After reading about them a little, they reminded me of C++'s 
 template template parameters. In C++ you can almost write something like 
 this:
 
 template template typename class collection
 struct Numbers {
   collectionint integers;
   collectionfloat floats;
 };
 
 So then you can write Numbersvector for a structure that contains 
 vectorT collections, and Numberslist for a structure that contains 
 listT collections. EXCEPT that it doesn't actually work, because vectorT 
 has two template parameters (the second one, the allocator, is normally left 
 at its default). Let's ignore that, though.
 
 So that brings me to my first question: is this what higher-kinded types 
 means? What is the difference, if any, between HKT and C++ template 
 templates?
 
 However, as a C++ developer I never actually used a template template 
 parameter because I didn't know they existed for a long time. So instead I 
 would have written this, which has the same end-result:
 
 struct VectorTrait
 {
templatetypename T
struct collection { typedef vectorT type; };
 };
 struct ListTrait
 {
templatetypename T
struct collection { typedef listT type; };
 };
 
 templatetypename Traits
 struct Numbers
 {
Traits::collectionint::type integers;
Traits::collectionfloat::type floats;
 };
 // Use NumbersVectorTrait for vectorT, NumbersListTrait for listT.
 
 This is clunkier, but it would have been a bit simpler if C++ supported 
 templatized typedefs:
 
 struct VectorTrait
 {
templatetypename T typedef vectorT collection;
 };
 struct ListTrait
 {
templatetypename T typedef vectorT collection;
 };
 
 templatetypename Traits
 struct Numbers
 {
Traits::collectionint integers;
Traits::collectionfloat floats;
 };
 // Now write NumbersVectorTrait instead of Numbersvector,
 //   NumbersListTrait instead of Numberslist.
 
 I have found that because of the existence of typedef, template template 
 parameters are never actually necessary; so far, I've never seen a situation 
 where the typedef-based solution wasn't almost as good. Also, I have found 
 that trait types filled with typedefs seem to be a more general thing than 
 template template; they allow you to do things that would be very 
 difficult or impossible without them. For example you can use 
 typedefs-in-a-struct to create circular references among types that don't 
 know about each other:
 
 // I call this a Combo; I don't know if the technique has a standard name
 struct MyCombo {
typedef ConcreteATraits A;
typedef ConcreteBTraits B;
typedef ConcreteCTraits C;
 };
 templatetypename Combo
 class ConcreteA { Combo::B* b; ... };
 templatetypename Combo
 class ConcreteB { Combo::C* c; ... };
 templatetypename Combo
 class ConcreteC { Combo::A* b; ... };
 
 Here I've created a network of types (ConcreteAMyCombo, 
 ConcreteBMyCombo, and ConcreteCMyCombo) that are linked together through 
 the Combo type MyCombo, so the types can all use each other, but none of 
 the types refer to each other directly. This design allows you to freely 
 swap in different implementations of A, B, and C; it has similar advantages 
 to dependency injection or inversion of control in languages like Java 
 and C#, except that the linkages are all defined statically at compile-time, 
 so no dynamic dispatch is required.
 
 Without the ability to define typedefs, this approach is not possible at 
 all if there is a cyclic relationship. Also, if the combo declares more than 
 three types, it becomes impractical to specify all those types on the 
 classes directly as type parameters.
 
 In C# I learned that this quickly becomes a