TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

Haskell: OOP vs type classes

75 点作者 rbxbx超过 13 年前

8 条评论

ekidd超过 13 年前
Haskell doesn't really do inheritance, unless you somehow get O'Haskell to work on a modern machine.<p>In place of inheritance, you have two mechanisms: algebraic data types and type classes. They work great for many programs, but neither of them is an exact fit for Java-style object-oriented programming.<p>An algebraic data type has a name ("Bool", in the first example below), and several constructors ("True" and "False"). Constructors can take positional and named arguments, and they can take type parameters:<p><pre><code> data Bool = True | False data Shape = Square { l :: Int, t :: Int, w :: Int, h :: Int } | Circle Int Int Int data Maybe a = Just a | Nothing </code></pre> Once you define an algebraic data type, you can't add new constructors. But you can write functions which match against the existing constructors at runtime, giving you a form of runtime dispatch vaguely analogous to method lookup:<p><pre><code> boolToString :: Bool -&#62; String boolToString True = "true" boolToString False = "false" </code></pre> So algebraic data types work great if you have one abstract interface with known set of concrete subclasses. It's a <i>really</i> great way to think about complex data structures with multiple types of nodes.<p>A type class is a little bit like a C++ template protocol: It says that a given type implements a set of functions. But as with C++ templates, it's effectively resolved at compile time. (Well, the implementation is quite a bit different, but that's the rough idea.)<p>Now, ADTs and type classes are great. But if you find yourself using crazy hacks to recreate an OO class hierarchy in Haskell, you're probably fighting against the language. Either structure your program differently, or find a different language.
评论 #3375385 未加载
评论 #3374342 未加载
gtani超过 13 年前
Well then, the expression problem. The guys who created scala and OCaml have opinions about this, no surprise (why not OOP and typeclasses?<p><a href="http://stackoverflow.com/questions/2807629/handling-incremental-data-modeling-changes-in-functional-programming" rel="nofollow">http://stackoverflow.com/questions/2807629/handling-incremen...</a><p>(message 20) <a href="http://groups.google.com/group/scala-debate/browse_frm/thread/96193eacf013a103/" rel="nofollow">http://groups.google.com/group/scala-debate/browse_frm/threa...</a><p><a href="http://lambda-the-ultimate.org/node/4400" rel="nofollow">http://lambda-the-ultimate.org/node/4400</a><p>---------------<p>and "ADT" i think real world haskell is correct in reservign this for abstract data types<p><a href="http://book.realworldhaskell.org/read/defining-types-streamlining-functions.html#deftypes.adt" rel="nofollow">http://book.realworldhaskell.org/read/defining-types-streaml...</a>
Chris_Newton超过 13 年前
It is unfortunate that two completely different concepts both happen to use the word "class" in their name. A related example is "return". People coming from a background in, say, C++ or Java will naturally have preconceptions about what these words mean, and will almost inevitably start by trying to apply them in Haskell world where they don't work.<p>It is particularly unfortunate because, with the wisdom of hindsight, I think classes as used in C++ and Java have been responsible for many problems over the years. This is fundamentally because they take two very common, very useful ideas -- modular design (separation of interface and implementation) and compound data types (struct/record/variant/etc.) -- and try to use a single tool to implement both at the same time.<p>Unfortunately, that creates all kinds of presumptions about how you write your functions, where the emphasis is always on one object being paramount or one data type controlling everything. For practical programming tasks, it may be more useful to model a situation using a set of related types to hold the data and a set of algorithms defined in terms of one <i>or more</i> of those data types (or more generally <i>collections</i> of one or more such types) to manipulate that data.<p>It's probably not an exaggeration to say that almost all of the most common modelling problems with C++/Java style OOP -- the "diamond pattern" with multiple inheritance, for example -- are due at least in part to this unwarranted emphasis on this/self/whatever you want to call it. Much of the rest is due to over-use of inheritance, which again has an underlying subclass-or-subtype ambiguity in what it represents -- and which again is perhaps emphasized by the whole one-object-to-rule-the-world philosophy even when what OOP would call containment or aggregation is a clearer way to model the situation.<p>Languages such as Haskell have never had this history of conflating modular design with structuring data, nor the resulting false friend of emphasizing one object/value/whatever in any given modelling context. IME, this is the big conceptual leap that is sometimes hard for those with a strongly everything-is-an-object background to make, though it's perhaps a little easier these days for anyone who has used C++ templates or Java generics. Once you make the jump, type classes and algebraic data types make a lot more sense.
jmartinpetersen超过 13 年前
There's a tech talk with Simon Peyton Jones giving an introduction to type classes in Haskell as well as discussing how it relates to OO at <a href="http://channel9.msdn.com/posts/MDCC-TechTalk-Classes-Jim-but-not-as-we-know-them" rel="nofollow">http://channel9.msdn.com/posts/MDCC-TechTalk-Classes-Jim-but...</a>
langsamer超过 13 年前
I think it is a bit silly to try to re-create OO with type classes or vice-versa. They are just two different modes of thinking and represent two different ways of architecting your program. Personally, I do find OOP a hoax, which leads to just horrendous code, but I'm sure either approach can be used to solve the problem at hand as long as you don't try to fit the round-peg in the square-hole.<p>For a case against OOP read : <a href="http://c2.com/cgi/wiki?ObjectOrientationIsaHoax" rel="nofollow">http://c2.com/cgi/wiki?ObjectOrientationIsaHoax</a>
tikhonj超过 13 年前
I haven't had time to read through the whole article (and I already know how type classes work :)) so I just have one little point to add.<p>As correctly put in the article, type classes can provide default implementations. However, one cute thing that was missed is that type classes can provide default implementations for <i>every</i> function, referencing each other:<p><pre><code> class Eq a where (==), (/=) :: a -&#62; a -&#62; Bool x /= y = not (x == y) x == y = not (x /= y) </code></pre> This way you can implement == <i>or</i> /=, and you get the other for free.<p>For me, the one new idea that made me understand why type classes are awesome was the read function: it's polymorphic on its <i>return type</i>. This means that you always give it a String and it returns whatever you need. This also means that you can have polymorphic constants--maxBound is the maximum of <i>any</i> bounded numeric type, so you can use it as an Int or a Float and it will always have the right value.<p>Overall, I now think that type classes are awesome. However, I also don't think a parallel to OOP is particularly helpful--I also learned OOP well before functional programming and found it easier to understand type classes by looking at how they were used than by comparing them to interfaces or templates.
rbxbx超过 13 年前
Speaking as someone who's brain has been broken by OOP, I found this article quite illuminating and would love to see more of the hardcore haskell/ML/FP guys weigh in.
评论 #3374334 未加载
评论 #3374781 未加载
nwmcsween超过 13 年前
I always thought OOP vs other paradigms is simply structuring the program, with enough time and work you could make a any program in any paradigm you wish. Why not pluggable paradigms?