To take another example, an iterator could be something like:
next :: T a -> a
hasNext :: T a -> bool
That's all an iterator is. The cool thing is that if you implement next and hasNext for a list, an array, a tree and a graph, you can all use them with the same code. That's what monads, functors and applicatives are.As for the culture part, I think Rust is the sweet spot. Types are here, but you also have explanations. I personally find explanations without types worse than types without explanations, but ideally you should have both. Of course that's assuming meaningful types.
I think this is a fairly standard functional representation of iterable entities:
next :: T a -> Maybe a
rest :: T a -> Maybe (T a)
We could (and you should) argue that this is correct by intuition, but it's also possible to sketch a proof that these structures all "behave" the same as lists would. We can first combine `next` and `rest` into a single function -- note that we can always interconvert between (next, rest) and step: step :: T a -> Maybe (a, T a)
This has the form of something called a "co-algebra", which consists of (1) a functor `F`, (2) a type `k`, and (3) and a function `k -> F k`. In this case, `k = T a` and `F = Maybe (a, -)`.The interesting thing is that the functor `Maybe (a, -)` can have many co-algebras, depending on which type and step function you pick. The type [a] -- that is, picking T to be [] -- gives a particularly special co-algebra, called the "terminal" coalgebra for `Maybe (a, -)`. In short, while any other choice of coalgebra may support additional operations, you can convert any one of them to a list without disturbing a process that only makes use of the nominated `step` function. They're observationally equivalent to lists.
That's true, but I was talking about iterators in general. My point was that functors, applicative and monads may seem weird and special, but we use the same thing in everyday life. Same thing about the signatures: iterator is that, just a signature, but nobody complains about it.
Your explanation about functional iterators is great, I think it shows really well how iterators are about treating any data structure as if it was the simplest data structure. In a imperative language, it's the array, in a functional language, it's the list.
Yes, and the parent I was replying to had only provided the type signatures.
Even more than that though, describing what something is is usually not sufficient. You also have to describe why it's useful, or rather what it's for.
This is analogous with comments in code - in well written code you don't need many comments telling you what the code is doing, it's often fairly clear. They're also for convenience not necessity because you can, with enough time, figure out what the code is doing because you have all the information. What are irreplaceable are "why" comments telling you why something is done. E.g. "this prints two newline characters at the end of the document" is inferrable, but "print two newline characters because X program is unreliable unless we end with a blank line" is invaluable.
The thing is, these things are very abstract. The signature is what they are and why they are useful. A way to think about them is that they were discovered. People wrote a lot of code, saw the same pattern come up over and over again, and named it so they can abstract over it and reason about it.
> This is analogous with comments in code - in well written code you don't need many comments telling you what the code is doing, it's often fairly clear. They're also for convenience not necessity because you can, with enough time, figure out what the code is doing because you have all the information. What are irreplaceable are "why" comments telling you why something is done. E.g. "this prints two newline characters at the end of the document" is inferrable, but "print two newline characters because X program is unreliable unless we end with a blank line" is invaluable.
I agree with you here. The problem is that it's very hard to describe why they are useful if you didn't encounter the problem they solve yourself.
But I think GP comment summarized it pretty well, it shows how they all relate to each other in a concise way. If its not enough of an explanation, ok, look for another.
Of course, there are lots of libraries that only have type signatures as documentation. I think most people think that's less than optimal, but the haskell community is much smaller than many others. So what you'll want to do is look for a blog post or something that explains it in more detail.
Possibly once you're immersed in the world and up to speed with Haskell type signatures are all you need. Unfortunately for people coming to the language we need more context to fit the pieces together, and the vast majority of documentation I found lacked that context.