6 ms·
It may even be fair to say that Haskell's typeclasses make it more like an object-oriented programming language. They have things like properties and multiple i
by wyc 9y ago
It may even be fair to say that Haskell's typeclasses make it more like an object-oriented programming language. They have things like properties and multiple inheritance. Even Wadler has a section leading with "Object-oriented programming." in his paper on parametric polymorphism:
https://people.csail.mit.edu/dnj/teaching/6898/papers/wadler88.pdf https://people.csail.mit.edu/dnj/teaching/6898/papers/wadler... (page 3)
- cies 9y agoObject is a sufficiently generic term, so that it can mean very different things to different people. Lumping state with some functions that implicitly have R/W access to that state is not possible in Haskell, not even with the powerful type-classes. Thankfully. Type-classes do allow interesting polymorphism tricks, that —as Wadler mentioned— allows Haskellers to use some of good parts of OO.
- wyc 9y agoYou're right; I still struggle to come up with a good catch-all definition for "object." On an unrelated note, I'm also still trying to figure out what DevOps is, aside from YAML and tears.
- cies 9y agoDevOps provisioning by software (hence the "dev") instead of by hand (manual-Ops). It is with cloud-native that it gets interesting. Cloud-native infrastructure (like k8s) usually replaces the traditional devops tools (like Puppet, Ansible and Salt). Also it brings the notion of "scrappable instances", "blue green deployments" and "stateless compute nodes". This is were it got really interesting, this is were the FP intuitions start carry over. :)
- wyc 9y agoInteresting last point! It does seem to be the trend, notably with large data sets: https://wycd.net/posts/2017-04-09-rpcs-for-moving-computation.html https://wycd.net/posts/2017-04-09-rpcs-for-moving-computatio...
- dons 9y agoLumping state with some functions that implicitly have R/W access to that state is not possible in Haskell s/not possible/possible, but highly discouraged/
- bad_user 9y agoPolymorphism — If you understand by OOP the single-dispatching made at runtime, then type classes are different because type classes are solved at compile time, the "vtable" (the dictionary of functions) being passed around isn't virtual and is provided per type, not per instance. Encapsulation — If you understand by OOP the encapsulation of data, then no, type classes have no such thing. Inheritance — type classes don't have inheritance. What they have are constraints (e.g. you can implement typeclass X for type T if a typeclass implementation Y also exists for T). So you can say for example that MonadError can be implemented only for types already implementing Monad. That's not inheritance, but composition. Most importantly perhaps and something that doesn't clearly follow from the above is that OOP as implemented in popular languages, including C++, gives you subtyping, whereas type classes do not. This has important ramifications. For example downcasting isn't possible. And you no longer have the "liskov substitution principle". And subtyping is actually incompatible with Hindley-Milner type inference. Also in actual usage the differences can be quite big — for example, if you view type classes as "restrictions" on what a type can do (like OOP interfaces are), you no longer need to add these restrictions on the types themselves, but on the operations, where you actually need them, while the data structure definition can remain free of such restrictions. This is called "constrained parametric polymorphism" btw. Which can't be achieved in most OOP languages that I know of, except for Scala and that's because Scala has "implicit parameters" which are equivalent to Haskell's type classes. At the end of the day, what a type class gives you is a way to transform a type name into a meaningful value. Imagine having a function like ... f: T => A But the T param is a type name. That's what type classes give you, whereas OOP does not.
- tathougies 9y agoAll you need is a GADT which carries around the type class constraint. data Object cls a where Object :: cls a => a -> Object cls a Now, the class `cls a` is carried around with the value `a`. You can even go one step further and reify the vtable by itself. data Dict c where Dict :: c => Dict which you can't really do in standard C++.
- leshow 9y ago> This is called "constrained parametric polymorphism" The more common terminology is ad-hoc polymorphism AFAIK.
- steveklabnik 9y agoRust's traits are basically typeclasses, and so people coming from an OOP background have often struggled to model stuff in a Rust-y way. The 17th chapter of The Rust Programming Language [1] tries to get into the differences, and explain this kind of stuff. It's really hard though, since what OOP means depends on who you ask. I enjoyed this post since it's kind of a mirror of this chapter, which was one of the hardest for us to figure out what to put in it. 1: https://doc.rust-lang.org/book/second-edition/ch17-00-oop.html https://doc.rust-lang.org/book/second-edition/ch17-00-oop.ht...
- harpocrates 9y ago> It may even be fair to say that Haskell's typeclasses make it more like an object-oriented programming language. The trick here is defining "object-oriented". In modern object-oriented languages, I usually assume that involves encapsulation of state inside of boxes called objects. In that sense, type classes are quite different. Methods on objects generally mutate or provide views into the contents of the box, while methods in type classes are just regular functions. Critically, there is no inner mutation or privileged view into data via type classes. > They have things like properties and multiple inheritance How do they have properties? Also, they don't have multiple inheritance - a type can only ever have one instance of any given typeclass. > Even Wadler has a section leading with "Object-oriented programming." I read Wadler's paragraph on object-oriented programming (bottom of page 3) more as a highlight of the fundamental _difference_ between type classes and object-oriented classes. The only similarity between typeclasses and classes are that they are the mechanisms by which runtime dispatch is achieved.
- mempko 9y agoOOP has nothing to do with classes, inheritance, especially multiple inheritance. It's about programming objects that communicate with each other. In fact Javascript and it's prototype system are much more OOP than say C++ classes, or worse, Java classes. We should call programming with classes and inheritance. COP, as in Class Oriented Programming. COP is especially appropriate because if you don't follow the type rules, you go to compiler jail.
- platz 9y ago> OOP has nothing to do with classes, inheritance, especially multiple inheritance. It's about programming objects that communicate with each other. That is the Alan Kay definition. I'm not sure I'd claim that is the colloquial, universal understanding of OOP apart from the HN crowd, though. (ask a LOB programmer what OOP is and observe what they say). I rather like the Alan Kay definition myself, but that is rather like having a Many Worlds understanding of quantum mechanics; Entirely consistent and arguably "correct", but not universally shared among practitioners. We should refine our language (e.g. COP), but it would be revisionist to ignore what the 90's and 00's understanding of the definition would be. I think it would be even more of a stretch to say that prototypal languages (javascript) are more OOP than non-prototypal languages, unless of course one is being a bit reductionist.
- munificent 9y ago> In fact Javascript and it's prototype system are much more OOP than say C++ classes, or worse, Java classes. I'm not sure what your ordering relation is here, but if it has something to do with how "purely object-oriented" a language is, then, sure, JavaScript is more OOP than C++ and Java since classes are not first-class in the latter. But Smalltalk, which is class-based, is even more OOP than JavaScript since in Smalltalk, constructor calls are simply regular method calls (unlike JS which has a special "new" keyword) and there are no primitive objects (unlike JS, which distinguishes between primitive types and their boxed forms, though it tries to obscure that fact). > COP is especially appropriate because if you don't follow the type rules, you go to compiler jail. Smalltalk, Ruby, and Python are all class-based OOP languages but do not have static type systems with lots of compiler errors.
- 9y ago