C++ Concepts vs Rust Traits vs Haskell Typeclasses vs Swift Protocols - Conor Hoekstra - ACCU 2021

preview_player
Показать описание
#Programming #Cpp #AccuConf
ACCU Twitter: @ACCUConf

------
C++20 comes with Concepts - one of the four major features of the C++20. This talk will explore a basic introduction to what Concepts are, how to use them and how to write one. The talk will also focus on how they compate to "adjacent" language features such as Rust Traits, Haskell Typeclasses and Swift Protocols. This talk will be a "must see" for programming language enthusiasts.

------
Conor Hoekstra
Conor Hoekstra is a Senior Library Software Engineer at NVIDIA working on the RAPIDS team. He is extremely passionate about programming languages, algorithms and beautiful code. He is the founder and organizer of the Programming Languages Virtual Meetup and he has a YouTube channel.

------

Future Conferences:
ACCU 2022 Spring Conference, Bristol (UK), Marriott City Centre:
2022-04-05 to 2022-04-09.
-------------------------
Рекомендации по теме
Комментарии
Автор

Regarding "constrain" and "consent" it depends on what you are talking about. In the Haskell example when you say f:: t -> t, the function should work on every type, so no constrains on the type, but that leads to constrains on the implementation (only identity is possible). By adding constrains to the types (e.g. Num t), you allow f to be different from identity, because it doesn't need to work on every type.

persianmaster
Автор

Great talk! I don't think that describing Swift's generics as 'constrained generics' is unintuitive though, I just think it's a case of whether you are viewing things as a caller on the 'outside' or the implementer on the 'inside'. As a caller to a method, on the outside, a T: Numeric is more constrained than a T because there are less types you can pass in or get back. Whereas, from the point of view of the function implementation, a T is more constrained than a T: Numeric because there is less you can do with it.

appalling
Автор

Man, that tea just kept spilling (
Anyway, great talk, Conor! Thank you!

yogthemuskrat
Автор

Great talk! I really liked the "constrain" vs. "consent" mental model.

A noteworthy difference in the two approaches is that with a C++ concept types may satisfy it implicitly, whereas with the typeclass approach you have to explicitly "extend" types to make the compiler aware of the connection (implementing an instance in Haskell, adopting a protocol in Swift, implementing a trait in Rust) in a way somewhat similar to how you implement an abstract interface in the OOP world with inheritance and overloading (but with compile-time function dispatch).
When you add a new concept it could automatically be satisfied by third-party library types that you depend on but cannot
change. This extends naturally to standard library types and even built-in types, which in my view is a great advantage of this approach. But maybe the idea of a typeclass is easier for most programmers to learn as a new language feature, especially if they come from an OOP background?

petterholmberg
Автор

In second example in Rust you could have used `&'static str` instead of `String`, that way you don't need to call `.to_string()` anymore and thus avoid heap allocation.

And it is also possible to re-write function definition to look more like D:
fn print_share_info<S>(s: S) where S: Shape { ... }

^ is useful for more complex bounds to be readable.

nazar-pc
Автор

About Rust's nice compiler messages: Have you tried to use `cargo clippy`? It is a linter that gives you even more nice messages about things that are technically correct Rust. Like it sometimes can tell you if you create an unnecessary temporary value or if you do something in an non-idiomatic way.

blenderpanzi
Автор

Dudu wtf!!! I didn't knew that you can use "auto" to create templates in C++! Thanks a lot man!

godnyx
Автор

Since you mentioned Nim:

from math import PI, pow
type
ShapeKind = enum Circle, Rectangle
ShapeProps = tuple[shape:string, area, perimeter:float]
Shape = object
case kind:ShapeKind
of Circle:r:float
of Rectangle:w, h:float

func =
case shape.kind
of Circle:($shape.kind, PI*shape.r.pow 2, 2.0*PI*shape.r)
of Rectangle:($shape.kind, shape.w*shape.h, 2.0*shape.w+2.0*shape.h)

const shapes = [ # <- shapes are compiletime resolved
Circle:Shape(kind:Circle, r:10).buildShapeProps,
Rectangle:Shape(kind:Rectangle, w:10, h:10).buildShapeProps,
]
for shape in shapes:
for prop, value in shape.fieldPairs:
echo prop, ": ", value
echo ""
echo shapes[Circle].area # <- A ShapeKind enumerated array of named tuples

# Output ->

# name: Circle
# area: 314.1592653589793
# perimeter: 62.83185307179586

# name: Rectangle
# area: 100.0
# perimeter: 40.0

# 314.1592653589793

megetmorsomt
Автор

1:18:00 To map types that almost fit. In C++ this has to be taken care by the library developer - provide knobs so the user can provide an implementation ("mapping"). These are called "extension points" and basically boil down to using non-member functions (so the user can "extend" his/her class with the needed functionality) and type trait specializations (so that the user can provide the needed "associated types"). We are at this situation more or less because concept_map was dropped from the original concepts proposal in order to simplify it. A concept_map would act as the impl X for Y in Rust.

YourCRTube
Автор

Sidenote: For Rust you can write the print function like this:

fn print_shape_info(s: impl Shape) { ... }

It does exactly the same, but if you have only one simple constraint on a parameter type and especially if you have multiple parameter types that can have different types (of the same or of different constraints) this is handy. Not that `fn foo<T: Shape>(a: T, b: T)` and `fn foo(a: impl Shape, b: impl Shape)` are different. In the second version a and b might be of different actual types (e.g. a is a Rectange and b is a Circle). Sometimes this is what you want, sometimes it isn't. Use what is appropriate.

blenderpanzi
Автор

37:00 D also allows the return type to be inferred; i.e., you can replace "int" with "auto".

Snarwin
Автор

Great takl! But what about dynamic polymorphism? How do traits and protocols compare to virtual functions and type erasure in C++?

jmelas
Автор

About type constraints are tot types like types are to values: Well, I think meta-classes are to types (classes) like types (classes) are to values. Funnily enough the dynamically typed languages Python and Smalltalk have powerful meta-class facilities, but not generics with type constraints (Python works on type hints, but it is extremely limited at the moment). In Python meta-classes derive from the class `type`.

blenderpanzi
Автор

Where is `let` as function declarator? Ocaml does this. Haskell also does this in non-toplevel or non-where blocks

slowpnir
Автор

Where can I find the second part of this talk?

mdyousufali
Автор

50:42 paraphrased: "C++ templates stamp out separate functions for each different type they get passed and therefore aren't parametric polymorphism"
This is how it works in most languages (e.g. C#, Rust, and I think D, Haskell etc.)! It doesn't work like that in Java or TypeScript because they use type erasure. (Which is the reason you can only use boxed types with generic functions in Java.) So do you mean that only Java and TypeScript actually support parametric polymorphism? I think there is a misunderstanding somewhere.

blenderpanzi
Автор

You realize that swift methods in classes are also non-const by default right?

rinket
Автор

1:22:37 "unless we're going to break ABI in a massive way" C++ does not have ABI

bart
Автор

Your Haskell example doesn't make sense. What you _should_ do is just implement the sum type, and then all functions will work.

vekyll
Автор

I know c++ has 40 years of baggage... but jesus Christ can't you say one nice thing about it? The entire time you're just saying all the other languages do it better than c++.

Why not say a few cool things that c++ concepts can do, something unique and interesting, something that they can do over the solutions in other languages? As a c++ programmer your talk was quite demotivating. But i dont think it HAD to be. 4/10

rinket