Re: D's type classes pattern ?
Thanks for the precisions on template constraint and template specialization...Indeed wath I want to do look like isInputRange constraint. Haskell have something like : //(Pseudo D-Haskell) void foo(InputRange R)(R r); //D equivalent void foo(R)(R r) if (isInputRange(R)); Except they call them type classes instead of template constraint and it is check at runtime instead of compile time for D. I am curious to know how isInputRange is implemented since I wanted to do kind of the same but I am afraid it's full of (ugly) traits and template trickeries where haskell type classes are quite neat and essentially a declaration of an interface. Let say I want to be able to add the type my algo deal with...I could do an isAddable wich looks if a+b compiles with traits...I wondered if you could check statically that the type could implement an interface *if it wanted to* that is, without inheriting it...
Re: D's type classes pattern ?
matovitch: I am curious to know how isInputRange is implemented since I wanted to do kind of the same but I am afraid it's full of (ugly) traits and template trickeries where haskell type classes are quite neat and essentially a declaration of an interface. Take a look at the sources and learn. They are sometimes tricky to get right, but it's not a problem of ugly syntax. I wondered if you could check statically that the type could implement an interface *if it wanted to* that is, without inheriting it... Template constraints don't require inheritance. Bye, bearophile
Re: D's type classes pattern ?
On Wednesday, 25 March 2015 at 08:55:14 UTC, bearophile wrote: matovitch: I am curious to know how isInputRange is implemented since I wanted to do kind of the same but I am afraid it's full of (ugly) traits and template trickeries where haskell type classes are quite neat and essentially a declaration of an interface. Take a look at the sources and learn. They are sometimes tricky to get right, but it's not a problem of ugly syntax. I wondered if you could check statically that the type could implement an interface *if it wanted to* that is, without inheriting it... Template constraints don't require inheritance. Bye, bearophile Yes I know that you don't need to inherit some InputRange interface to be able to check a user defined type is an input range. And template constraints are more powerful/general than type classes but it's harder to get right for the beginner. I will definetly look at the code anyway. I was looking at : interface IInputRange(InputRange) {...} class TypeClass(T,I) : I!T { alias t this; T t; } void foo(InputRange) (InputRange inputRange) if (isInstanciable(TypeClass!(InputRange, IInputRange)));
Re: D's type classes pattern ?
On Tuesday, 24 March 2015 at 16:56:13 UTC, matovitch wrote: Thanks, just to be clear : void Bar(T : Foo)(T t){ } is the same as void Bar(T)(T t) if (is(T == Foo)){ } and it is checked only at compile time ? (for the runtime I know that what interface were meant for ;)). Ali already mentioned the difference between == and :. In addition to that, template specializations (like `Bar(T : Foo)(T t)`) and template constraints (like `Bar(T)(T t) if(is(T : Foo))`) are similar but generally not interchangeable. A template with a specialization is considered a better match than one without. Whereas a template constraint doesn't add to the quality of the match. An example: module test; import std.stdio; void f(T)(T t) {writeln(generic);} void f(T : int)(T t) {writeln(with specialization);} void f(T)(T t) if(is(T : Object)) {writeln(with constraint);} void main() { f(some string); /* - generic */ f(42); /* - with specialization */ version(none) f(new Object); /* Doesn't compile, because it matches both the generic version and the one with the constraint. */ }
Re: D's type classes pattern ?
On 03/24/2015 08:50 AM, matovitch wrote: Lets say I want to implement some generic algorithm. I would like to checks the types passed to my algorithm implements a specific interface. I think you are looking for template constraints. Look at isInputRange's implementation: https://github.com/D-Programming-Language/phobos/blob/master/std/range/primitives.d#L143 Then you can do: void foo(Range)(Range range) if (isInputRange!Range)// -- { // ... } I have some explanation and examples here: http://ddili.org/ders/d.en/templates_more.html#ix_templates_more.named%20template%20constraint Ali
Re: D's type classes pattern ?
On 03/24/2015 09:56 AM, matovitch wrote: just to be clear : void Bar(T : Foo)(T t){ } That means if T can implicitly be converted to Foo. is the same as void Bar(T)(T t) if (is(T == Foo)){ } That means if T is exactly Foo. and it is checked only at compile time ? Yes to both. Ali
D's type classes pattern ?
Hi, It's been a long time since I coded some d code... sorry I take the lazy way asking for advices. :D Lets say I want to implement some generic algorithm. I would like to checks the types passed to my algorithm implements a specific interface. interface IStuff(Stuff) { void foo(); } class TypeClass(T, I) : I(T) { alias this T; } void myAwesomeAlgo(Stuff) (TypeClass!(Stuff, IStuff) stuff) { stuff.foo(); } Well it seems that I have worked out my question in trying to formulate it...Would something like this work ?
Re: D's type classes pattern ?
More like : import std.stdio; interface IStuff(Stuff) { void foo(); } class TypeClass(T, I) : I(T) { alias this stuff; T stuff; } void myAwesomeAlgo(Stuff) (TypeClass!(Stuff, IStuff) stuff) { stuff.foo(); } struct MyStuff { void foo() { writeln(Hello World !); } } void main() { alias TypeStuff = TypeClass!(MyStuff, IStuff); TypeStuff stuff; myAwesomeAlgo(stuff); } Doesn't compile btw : kmeans.d(8): Error: members expected kmeans.d(8): Error: { } expected following aggregate declaration kmeans.d(8): Error: Declaration expected, not '(' kmeans.d(12): Error: unrecognized declaration
Re: D's type classes pattern ?
Well, just follow that link to the code...it almost compile : http://dpaste.com/3JNP0QD.
Re: D's type classes pattern ?
Wait no ! In that case my type will have to inherit the interface...I don't want that, checking without inheriting...I know thats weird.
Re: D's type classes pattern ?
On Tuesday, 24 March 2015 at 16:44:54 UTC, weaselcat wrote: On Tuesday, 24 March 2015 at 15:51:00 UTC, matovitch wrote: Hi, It's been a long time since I coded some d code... sorry I take the lazy way asking for advices. :D Lets say I want to implement some generic algorithm. I would like to checks the types passed to my algorithm implements a specific interface. interface IStuff(Stuff) { void foo(); } class TypeClass(T, I) : I(T) { alias this T; } void myAwesomeAlgo(Stuff) (TypeClass!(Stuff, IStuff) stuff) { stuff.foo(); } Well it seems that I have worked out my question in trying to formulate it...Would something like this work ? interface Foo{ } void Bar(T : Foo)(T t){ } but interfaces enable runtime polymorphism, you can just accept the interface itself void Fun(Foo foo){ } Thanks, just to be clear : void Bar(T : Foo)(T t){ } is the same as void Bar(T)(T t) if (is(T == Foo)){ } and it is checked only at compile time ? (for the runtime I know that what interface were meant for ;)).
Re: D's type classes pattern ?
To resume my goal (last lonely message I promise), how can you statically check a type implement an interface without making this type inherit the interface (otherwise std.traits would do it) ? ps : it seems to me that this is exactly what the haskell compiler do with type classes - layman opinion
Re: D's type classes pattern ?
well, alias this is the issue here. interface I { void foo(); } struct S { void foo() {} } class C : I { S s; alias this s; } don't compile...if you have any idea to do otherwise I am greatly interested. Thanks !
Re: D's type classes pattern ?
On Tuesday, 24 March 2015 at 15:51:00 UTC, matovitch wrote: Hi, It's been a long time since I coded some d code... sorry I take the lazy way asking for advices. :D Lets say I want to implement some generic algorithm. I would like to checks the types passed to my algorithm implements a specific interface. interface IStuff(Stuff) { void foo(); } class TypeClass(T, I) : I(T) { alias this T; } void myAwesomeAlgo(Stuff) (TypeClass!(Stuff, IStuff) stuff) { stuff.foo(); } Well it seems that I have worked out my question in trying to formulate it...Would something like this work ? interface Foo{ } void Bar(T : Foo)(T t){ } but interfaces enable runtime polymorphism, you can just accept the interface itself void Fun(Foo foo){ }