[HN Gopher] Introduction to Haskell Typeclasses
___________________________________________________________________
Introduction to Haskell Typeclasses
Author : ingve
Score : 111 points
Date : 2022-04-27 07:59 UTC (15 hours ago)
(HTM) web link (serokell.io)
(TXT) w3m dump (serokell.io)
| da39a3ee wrote:
| Wouldn't it be helpful to use the word "interface" in the article
| (and other docs) since that's basically what they are known as in
| other languages (or "trait" in Rust and Scala). I'm sure we can
| have a really long thread on the difference between these
| concepts in different languages but wouldn't it help beginners to
| be told that those are more or less the same thing?
| prezjordan wrote:
| I really enjoyed this, thanks! I've been writing OCaml a lot and
| wish it had the expressiveness of `instance Eq Pokemon where`.
| somewhereoutth wrote:
| Would it be fair to say that typeclasses are a formalisation of
| _ad-hoc_ polymorphism? With all the good and bad things that come
| with that.
| dboreham wrote:
| Pretty much.
| mumblemumble wrote:
| I may be way off on this, but I like to think of them as a
| bridge between ad-hoc and parametric polymorphism. Or maybe an
| ad hoc wolf in parametric sheep's clothing.
|
| Functions and types that refer to typeclasses are
| parametrically polymorphic insofar as they don't refer to a
| specific implementation of that type. This is quite different
| from run-of-the-mill function overloading, where you must
| supply separate implementations for every set of types you want
| to support.
|
| But, unlike how parametric polymorphism works in OOP, late
| binding is not an option. At the use site, the typeclass
| implementation you want to use must be statically resolvable.
| In that respect, it does behave like function overloading.
| HelloNurse wrote:
| Very well written, but an introductory tutorial shouldn't ignore
| fundamental difficulties like multiple conflicting instances of
| the same typeclass for the same type.
|
| Your example would be a good fit, since Pokemon can be
| "naturally" ordered by number, by name, by which one has more
| types, and in infinite other ways.
| _query wrote:
| If this post got you interested in learning more about Haskell
| and you want to see type classes in some real code, a great
| starting point for Haskell is IHP :)
|
| IHP is a new Haskell framework with a focus on actual building
| applications. Imagine the productiveness of rails combined with
| the typesafety of Haskell.
|
| It's now already the biggest Haskell web framework, we just hit
| 3200 GitHub stars. I belive Haskell can reach a lot more than
| it's currently doing if we get things easy to use.
|
| If you want to build a web app with Haskell and play with type
| classes check it out: https://ihp.digitallyinduced.com/ GitHub:
| https://github.com/digitallyinduced/ihp
| okkdev wrote:
| I'm waiting for the new release because of the M1 fix that got
| merged...
| [deleted]
| fn-mote wrote:
| I'm not sure what this adds over LYaH. Possibly it is useful
| because you have to survive until LYaH Chapter 8 for "Typeclasses
| 102"? [1]
|
| The basic post was fine I didn't see any lightbulb moments. It
| works through an example showing how to add your own data type to
| Eq and Ord.
|
| The later post, "What's That Typeclass: Monoid" could have been
| interesting. To me it went to mathematically-abstract. Like every
| other Haskell post.
|
| Example quote: "...because a semigroup is a monoid without an
| identity element..." To be fair, they have defind SemiGroup, but
| really -- who is the audience for this?
|
| This is good for a laugh though:
|
| > Why do you need monoids?
|
| > In general, monoids are not very advanced, interesting, or
| cool.
|
| [1] http://learnyouahaskell.com/making-our-own-types-and-
| typecla...
| dmkolobov wrote:
| Respectfully disagree about monoids! Plenty of cool stuff
| there, here's one of my favorites, a diagramming library built
| around monoids:
|
| https://repository.upenn.edu/cgi/viewcontent.cgi?article=177...
| mhitza wrote:
| Monoids are pretty cool in theory, and at the same time, the
| tool I use least of when working with Haskell.
|
| This page [0] really shows how elegant Monoid comprehension
| would be when implementing SQL-like operations within pure
| Haskell code. (Goes over desugaring, implementation details and
| comparison to list/monad comprehensions, just jump down to
| examples)
|
| [0]
| https://lptk.github.io/programming/2018/10/04/comprehending-...
| chas wrote:
| Funny enough, monoids/semigroups are one of my favorite parts
| of Haskell and I really miss having an explicit abstraction
| for them in other languages.
|
| A lot of the code I write is looping over all of the values
| of a data structure to either look for a certain condition
| being true (any/all boolean monoid), look for an extremal
| value (min/max semigroup), or combine all of the values in
| the data structure (sum/product/average monoid). The product
| of a monoid is also a monoid, so if you want to do two or
| more of those operations at once, the code remains simple and
| orthogonal while only traversing the structure once.
|
| In particular, all of the those operations are nicely
| expressed as one-lines using foldMap (https://hackage.haskell
| .org/package/base-4.9.1.0/docs/Data-F...). If you have a data
| structure called `xs` and each element in data structure has
| an integer field called `size` you can do the following by
| using foldMap with different Monoid instances.
|
| Sum the sizes: let (Sum total_size) = foldMap
| (\x -> Sum (size x)) xs
|
| Check if any size is greater than 5: let (Any
| over_threshold) = foldMap (\x -> Any ((size x) > 5)) xs
|
| Do both in one pass: let (Sum total_size, Any
| over_threshold) = foldMap (\x -> (Sum (size x), Any ((size x)
| > 5))) xs
|
| Get the first entry with a size greater than 5:
| let (First over_threshold) = foldMap (\x -> First (if (size
| x) > 5 then Just x else Nothing)) xs
|
| Get all entries with a size greater than 5:
| let over_threshold = foldMap (\x -> if (size x) > 5 then [x]
| else []) xs
|
| Since all of these operations are associative, we can
| completely change the data structure or run the operations in
| parallel or concurrently and the code will still behave
| exactly the same. These nice properties mean that when I'm
| thinking about these sorts of tasks in any language, I think
| about what monoid or semigroup captures a given operation,
| rather than any of the mechanics of writing the loop. I find
| clarifies my thinking a lot.
| aroccoli wrote:
| Thank you for the feedback!
|
| To compare with Learn You a Haskell, I wanted to provide a
| different option / way of grasping the concept with, hopefully,
| examples that are relatable to some people more than LYAH.
| Having a few different explanations of the same thing is not a
| bad thing in my eyes since different things click with
| different people.
|
| Regarding Monoid article -- it is sad to hear that since my
| goal was to provide something that would be unlike the
| "mathematically-abstract" posts. It has plenty of examples and
| a rather long exposition, and I am not sure how much more it is
| possible to improve it without losing any meaning for the word
| "monoid".
|
| Semigroups and monoids is a rather awkward moment there, I
| didn't manage to find a perfect way to cover that. But, to be
| honest, I did mention what a monoid is plenty of times, and I
| did mention what an identity element is several times as well.
| So a careful reader should be able to imagine what a semigroup
| is if necessary.
|
| Anyway, thank you for reading the articles and pointing my
| attention towards that. I will for sure look at that part
| again. :)
|
| -- Author
| m1kal wrote:
| I liked the text about typeclasses. It is a standalone piece,
| "Typeclasses 102" in LYaH is a part of a chapter of a bigger
| piece. I think you achieved your goal - your Pokemon example
| is simple to grasp and shows how to derive type classes and
| implement functions by hand:)
|
| (not commenting about monoid/subgroup part)
___________________________________________________________________
(page generated 2022-04-27 23:02 UTC)