getify / Functional-Light-JS

Pragmatic, balanced FP in JavaScript. @FLJSBook on twitter.
http://FLJSBook.com
Other
16.6k stars 1.96k forks source link

Chapter 9: strings aren't functors – suggest using trees instead #179

Open glebec opened 5 years ago

glebec commented 5 years ago

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, Strings 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.

getify commented 5 years ago

Thanks for the suggestion!