Description
In #72 @DrBoolean already pointed this out, but since that (closed) issue addressed several sub-issues I think it's ok to make a single issue for this.
In (now-)Chapter 9, you use String
as an example of functors. However, String
s aren't actually functors, because the things inside them cannot be any arbitrary type. In other words, there is no such thing as a "String of type x
" – strings are always composed of characters and nothing else.
-- an `Array of a` can be transformed into an `Array of b`
Array.prototype.map :: [a] ~> (a -> b) -> [b]
-- a `String of chars` cannot be transformed into a `String of <other>`
String.prototype.mapLike :: String char ~> (char -> b) -> String char
-- (`b` values are turned into chars implicitly)
Instead of strings, I might suggest that the most intuitive example (for JS devs) of a functor apart from Arrays would be Trees.
-- a `Tree of a` can be transformed into a `Tree of b`
Tree.prototype.map :: Tree a ~> (a -> b) -> Tree b
The downside, unfortunately, is that trees are not a built-in first-class data structure, but must be implemented. Of course, that is not especially complicated, though the details (class-based? factory? prototypal map method? top-level map function?) will depend on your particular taste.
Other examples… Promise
acts as a functor sometimes, though not all the time (due to the difference between returning values vs. returning promises in then
); event emitters / RxJS observables can act as functors, though these are even farther from vanilla JS built-ins; functional idioms like Maybe, Either, Tuple… personally, I think Tree is a better candidate than these less-universally-familiar entities.