6 ms·
What I find confusing with Haskell is that the keywords don't seem to be consistent with the concepts they're meant to express. As someone new to Haskell I lear
by rhizome31 13y ago
What I find confusing with Haskell is that the keywords don't seem to be consistent with the concepts they're meant to express. As someone new to Haskell I learnt that the `class` keyword doesn't express the object-oriented concept of class, but the concept of type class, which is different. Fair enough. What about declaring types then? That must be `type`, right? Nope, `type` is for creating type aliases. OK, surely that must be `newtype` then? Wrong again, `newtype` is also for declaring aliases. All right, to declare a new type, you don't use `newtype` nor `type` you use `data`. But be careful, the part that has the `data` keyword is still called a type constructor, whereas the part that does not have the `data` keyword is called a data constructor.
OK so let's recap, you create a new type with `data`, which is formed of a type constructor that starts with the keyword `data` and a data constructor which doesn't start with `data`. To create aliases you use `type` and `newtype` and to create type classes you use `class`.
Now how do you call the type class of things that can be mapped over? Surely that must be something like `mappable`?
- adimitrov 13y agoThe designers of Haskell (and Haskell is one of the few successful design-by-committee languages,) were not doing things "your way" (where I assume you are a working programmer, with knowledge of some or even many traditional imperative languages.) They were PL researchers. Used to ML, Common Lisp, Ada, and, most importantly, Mathematics and Category and Type Theory. `data` introduces an algebraic data type, so it makes sense to use data as a keyword. `type` and `newtype`, on the other hand, are programmer's conveniences: both carry no runtime cost, they are not actually part of the semantics of the backend language. `map` is a function that's really just a specialization of `fmap`. Now, my category theory is a bit weak, but if I'm thinking correctly here, `fmap f` is an endofunctor in the category of functors, and so it makes perfect sense to call "mappable" Functor. There's also "Traversable," which works pretty much like a fully-fledged "mappable" with all extras, but also requires a Functor instance. Keywords, and idiosyncrasies of a syntactic nature are really just superficial. The actual elegance of the language is its type system. (The actual warts of the language are, for the most part, also in the type system; records for example.) The latter criticism about `mappable` is really just due to the fact that you haven't gotten used to the underlying theory (and I don't blame you, it's hard.) But getting used to it can be rewarding. I'm not saying it's going to make you a better programmer (I'm not necessarily of that opinion,) but it's rewarding in its own right. Oh, and the difference between data constructors, type names, and, later, kind names (with promotion, since 7.4,) can be confusing. I sometimes find it an oversight that they are not distinguished syntactically, I think that would greatly help most newbies, and sometimes even make things easier to read and understand for veterans, too.
- rhizome31 13y ago+1 for your thoughtful reply. I've tinkered with other functional languages (Erlang, Scheme and Clojure), but Haskell is a stranger beast.
- tel 13y agoScheme, Clojure, and most of Erlang are on an entirely different side of a fairly large chasm within the lay term "functional programming". Haskell, ML, Ada, Coq, and even some parts of Scala are just entirely different beasts. The underlying math is far more pronounced, leadi to new terminology and power.
- klibertp 13y agoAda?! It's purely imperative, type-safe language, no? At least that was the impression I got when it was forced on me at university. Also, ML? I know OCaml a bit, but according to this comparison: http://adam.chlipala.net/mlcomp/ http://adam.chlipala.net/mlcomp/ Standard ML has a "ref" type, which in effect allows mutable state. While it lack a bit of a syntactic sugar for this, OCaml's mutable record fields are implemented in terms of refs, so in the end SML isn't "more functional" in this than OCaml. Also, according to this answer (didn't check specs) SML has at least a WHILE loop: http://stackoverflow.com/questions/818324/loops-in-sml-nj http://stackoverflow.com/questions/818324/loops-in-sml-nj which is typical to imperative languages. OCaml makes no attempt to outlaw side-effect (I suppose SML is similar), it allows them explicitly by introducing functions which return () (unit type), which are called purely for their side-effects. There is even List.iter function, which accepts a function executed for each element only for side-effects. And side-effects are not restricted in any way. On the other hand Erlang has nothing like that - no loops, no mutable state in the language and it's side-effects are restricted to message passing. While Scheme and Clojure, too, allow mutable state and non-pure functions, the default is immutable and pure for almost everything. In Racket the most used data-structure, a pair (and lists by extensions) is immutable by default and all the functions working on pairs and lists are pure. There is another type, "mutable pair", which is used to construct mutable lists, but I haven't seen it used yet. Coq is not even turing complete. Anyway, I much prefer talking about "functional style" than "functional programming"/"functional languages". If you think that one cannot use monads outside of Haskell - you're wrong. The same applies for lazy evaluation, which is available in many languages as extension or special syntactic construct in the language itself. EDIT: I realized that parent probably thought of AGDA instead of ADA. And so I just installed it to check it out :)