You’re basically right.
In this specific instance (with
do etc) it’s not quite as general as ANY type whatsoever. In fact the type is constrained in a particular way which you don’t have to understand right now unless you want to.
(and if you want to understand it right now, then what you need to understand is that
Maybe is just one of many types that can be an instance of the
What i meant by polymorphic here is that what actually happens when you use
<- depends on the type this
do block is working with. So for
Maybe that would be "pull out the value from a Just or else short circuit to
Either, which is a slightly more sophisticated
Maybe it would be “take the Right value or short circuit to Left”.
What’s sort of amazing is that in the case of a List or Array it would be “take all the values out of this list” and in the case of Aff it would behave like a callback or promise. So that’s very polymorphic in that they’re very different abstractions but it only works because each one has a (lawful) instance of
Does that clarify things?
I think an FP person would entirely skip regular expressions and just use parser combinators like string-parsers.
Also, have you read through my overview of the
Monad type class hierarchy?
@smilack Thank you so much for your code example and explanation! The last code example really helps me understand how
Maybe work, and now I understand how powerful
do is and how can it be used with
Um can you explain more on the part of skipping regular expression? I am sure there must be a reason for FPers to do that, but this is the first time for me to hear that.
I have just started that chapter today! It seems more understandable after I realize Functor is just a container for storing values, which has exactly answered my own question.
Opinions differ on this point, but I feel that regular expressions are very difficult to read since they cram so much information into such a small space. I will almost always prefer libraries like
string-parsers or even just the standard string manipulation functions in
strings in production code as a result. I think regular expressions are best used in quick and dirty scripts or for tools like
grep, not production code.
I share the same feeling with you that Regex is very difficult to understand, especially in Purescript where Regex Literal is not a thing!
I tried to learn how to use
string-parsers and read the code example here, but I feel confused as I still see Regex there. How does a string parser work actually? How is it different with Regex?
You might find this link helpful for understanding the basics: https://remusao.github.io/posts/whats-in-a-parser-combinator.html
Basically, a regex isn’t composable, is hard to read, and is very easy to get wrong. Parsers such as
string-parsers have three parts to it:
- ‘atomic’ code that parses an individual part of the string (e.g. the next part in this string is the text
combinator code that combines atoms into something useful (e.g. use the same
banana parser multiple times, so that it will match 3 times on the text
monad class hierarchy to “glue” combinator and atomic parsers together, so that each one is executed sequentially and gets you what you want.
The example you looked at above can use regular expressions as an atomic parser. So, it does allow interleaving of the two, but clearly the combinator approach is much easier to read than using just regular expressions.
Still, as Harry pointed out, if you need something quick and dirty, then regex is fine. If you want more control, readability, and modularity, I’d reach for
string-parsers. I will say, however, that the error messages in that library are not the best right now. That’s part of the tradeoff we have with how that library is designed AFAIK.
@JordanMartinez Your comment is really helpful, thank you! Now I have an overview of how does it work.