4 ms·
Haskell completely has something you can mistake as an object system! The entire typeclass machinery works that way less classes and inheritance. There's even a
by tel 12y ago
Haskell completely has something you can mistake as an object system! The entire typeclass machinery works that way less classes and inheritance. There's even a highly functional subtyping relation.
- seanmcdirmid 12y agoType classes work strictly over values, with none of the naming machinery to give these values names and identities. Type classes only resemble classes in their unfortunate label; subtyping and polymorphism isn't really exclusive to OOP (with the exception of name-oriented nominal subtyping). The only way to create an object in Haskell is through giving it a GUID of some kind.
- tel 12y agoI'm not claiming typeclasses are classes, but more like modules and that modules achieve at least some of OO. Entity-like identity is a notably more difficult thing to pull off, but still is easily embedded in IO or ST. I'm not saying it's a complete OO implementation, but instead that it's not so far as to be completely unconfusable, though it might be hard to, say, do Smalltalk-in-Haskell.
- seanmcdirmid 12y agoTypeclasses don't give you any specific to OO: they are abstractions over values and that's about it. You wouldn't be able to emulate an existing OO system in Haskell, and anyways, it wouldn't bring you closer to "talking about" and "thinking in terms of" objects. My point that OOP is essentially "thinking in terms of named objects" whereas most of what Haskell focuses on is "expressing math by composing anonymous values." I believe this starting from a design perspective is the best way to highlight the real differences between OOP and pure FP.
- tel 12y agoI disagree, but I think we'd have to go to definitions to make headway on this conversation, so I'll back out. As final thoughts: while type classes give abstraction over values, (a) those values encompass HKTs so they can also be effectual in various ways and (b) universally quantified bounded types are a basically final algebras and codata goes a long way toward modeling objects. Between those two I think you can give OO in Haskell a run.
- seanmcdirmid 12y agoWe then have to argue about what objects really are, and there isn't much consensus :) I don't think my design-oriented linguistic definition is very popular, but it contrasts nicely with pure functional programming; otherwise there is a lot of overlap and I don't think we can say anything very interesting about their differences.
- tel 12y agoYep, exactly :) I don't find definitional wars interesting, and I'd, in the stream of everyday things, be very sympathetic to "OO and FP are different because they were built from different POVs". The only reason I am being a stickler is that I'm pretty interested in the idea that both FP and OO have a representation in type theory/category theory/logic and thus can be put into common representation. Haskell definitely isn't the best OO language, but if you squint hard enough you can see OO in it much like you can see FP in C's function pointers: painfully. Seeing FP in C helps you examine the implementation challenges of FP. Seeing OO in Haskell helps you pick apart the different semantic pieces which build to form OO.
- seanmcdirmid 12y agoI would go farther and say Haskell is the only popular general purpose language that can get away without exposing programmers to object-like abstractions in the general case. Of course, these languages are general enough that you could probably shove whatever paradigm you wanted on top of them, but they do optimize for a particular kind of paradigm. A type theorist's definition of OO will be quite different from a generalist's. For type theory, various kinds of polymorphisms mostly overlap between paradigms (e.g. generics and structural subtyping are useful in OOP), but nominal typing is both commonly associated with OOP and relatively useless in FP languages to be a distinguishing feature. This also dovetails with my named-oriented definition of OOP: objects have identity, but their types have identity also. If you come at it from the FP perspective, identity for objects AND types aren't very desirable...there are no meaningful names in math!
- dllthomas 12y agoI feel like the nearest thing to OO in Haskell in common use is the records-of-closures pattern. Still doesn't have persistent identity, of course.
- tel 12y agoRecords-of-closures is pretty much what I'm talking about. There is a notion of identity when those records are recursive, though the state management is still manual (as you'd expect). data Complex = { rotate :: Degrees -> Complex } -- thus -- rotate :: Complex -> Degrees -> Complex where `rotate` is a state transformer and thus produces a notion of identity.
- dllthomas 12y agoI think it's a stretch to say this, itself, provides any notion of identity. You could certainly implement identity with any of the myriad ways of maintaining references with state, of course.
- tel 12y agoOf course you're right, but I think a function like Complex -> Radian -> Complex offers two points of view. You can see it as a function which transforms complex numbers or a function representing an update to the internal state of a Complex object. The second highlights the need to keep track of identity. Throwing an STRef into the mix just gives you a particular kind of history—one which only retains the "now". Which is all sort of obvious and meaningless, but I still think it's interesting to think about. I think coalgebras tend to force thinking in terms of identity in this kind of way.