4 ms·
Let's describe this in a way that makes sense to me, a C# programmer. In C#, there's a function called Sum. It takes an IEnumerable<int>. There's an overload fo
by moomin 11y ago
Let's describe this in a way that makes sense to me, a C# programmer. In C#, there's a function called Sum. It takes an IEnumerable<int>. There's an overload for IEnumerable<double>. There's no way to express "is a number" in C#, so it's just special cased. In Haskell, however, there is:
sum :: (Num a) => [a] -> a
Which means: for any a which is a number, sum can be used to add up a list of as.
However, going back to the C# example, you'll note we said IEnumerable<T>, not List<T>. In C#, the container is general, but in Haskell it's specific. And since IEnumerable is an interface, this actually means "any type that is enumerable". Haskell has an analogue of IEnumerable called Foldable.
So, what we _really_ wanted sum to say was "sum is a function that, for any container f that is foldable, for any type a that is a number, takes an f of a and gives you an a".
sum :: (Foldable f, Num a) => f a -> a
This is the AMP style version of sum. Some people hate it, I love it.
However, there's another piece of background to this that the email doesn't mention: the Haskell Platform is under attack itself. There's a new solution called stack which is, to my mind, easier to use and less likely to bite you with version conflicts. And whether HP should continue to be the "default" recommended way of starting with Haskell is, at best, controversial.
In short: there's plenty of people who won't miss his work on Haskell Platform, but losing Mark himself is a loss.
- tinco 11y agoAnother hint of intuition for C#'ers out there. Foldable is like IEnumerable, and Traversable is a bit like ICollection. Some are a bit unhappy with the names too, even though they really make sense from the category theory sense. A thing about Foldable is that you can fold over it (obviously) but you can't necessarily map over it because in Haskell the general map (fmap of the Functor typeclass) has the law that `map (f1.f2) enum == ((map f1) . (map f2)) enum` but for example for Set this law won't hold because the intermediate set might drop elements identical elements that would not have been identical would the f1.f2 been applied in direct succession. See [0] for an example. Why fmap has this law I don't know, but Functor is super fundamental in Haskell's types so you can bet it's there for a good reason. Note that this Foldable-Traversable-Functor introduction into Prelude is not complete yet. For example the map in prelude is: `map :: (a -> b) -> [a] -> [b]`. If this movement continues it will possibly be `map :: (Functor f) => (a -> b) -> f a -> f b`. People are super scared of the name Functor, so I think that's why it's not been adopted yet. It should possibly be renamed to Container or Mappable to be more in line with what general developers expect. Would prelude's map be made equal to fmap however, it would make prelude super powerful. It would suddenly work on any Functor type, not just List. [0] https://www.fpcomplete.com/user/chad/snippets/random-code-snippets/set-is-not-a-functor https://www.fpcomplete.com/user/chad/snippets/random-code-sn... p.s.: if you don't grok typeclass, call it classclass instead, i.e. class of classes. And then think about how C#'s Interface also defines a class of classes.
- kqr 11y ago> Why fmap has this law The law is the only law of fmap, which is the "structure preserving law". It means that if you apply a function to each element of the structure, you cannot change the shape of the structure. This structure preserving property means you can safely apply any function (even ones you don't know what they do) and you can be safe you're not losing information beyond what the function takes away. > It should possibly be renamed to Container or Mappable to be more in line with what general developers expect. Mappable would be a truthful name. Container is not a good name because far from all Functors are containers. You can map over a lot of things (I/O actions, functions among others) which are not intuitively "containers", unless you revise your intuition of "container" to mean "mappable". :) The good thing about calling it for what it is – Functor – is an argument commonly lifted by Edward Kmett: when you're honest about what you're dealing with, you instantly give people access to 80 years of collective knowledge about the thing.