You have the signature for `useCache` wrong. I defined it above (`Cache -> a`). Notice the concrete type...
I cannot stress this enough. You do not need to remove the possibility of a value not existing in order to compose a simple, coherent program. This is because `Maybe` is designed to handle all of the extra ceremony involved with utilizing such values. You only need to use `>>` (map) instead of `|>` (pipe) when invoking your functions. That is it.
All of the above is really beside the point though, because I am not arguing that one way is necessarily better than the other. I am arguing that the author's post is titled "Parse don't validate", that the perfect construct is right there to exemplify how parsing unstructured data into/through a system can be done, but then the author eschews it in favor of... validation (with what appears to be some tricks to fool the compiler)!
If your guard against an invalid state is to throw an exception you are validating. Attempting to redefine the terms to fit a particular narrative is a distraction that serves no one.
> Neither I nor the author is unaware that there are many combinators that make this more convenient than explicit matching against Just/Nothing but doing so is strictly worse than returning a FilePath directly
I'd like you to define "strictly worse" here. In order for "strictly worse" to make any sense we would need to define "strictly better" to mean something like: "to have a reference to a variable
in this particular scope that is definitely a `FilePath`". But why are variables in this scope (`main`) so important? You can get reference to a `FilePath` directly whenever you need it through a `Maybe`:
useFilePath :: FilePath -> a
maybeFilePath <- (getConfigDirs >>= head)
maybeFilePath >> useFilePath
This is opposed to something like:
filePath <- getConfigDir // might throw
filePath |> useFilePath
There is no difference in behavior and only a slight difference in implementation. I suppose if you
really really wanted to `print` the value of `FilePath` from `main` (and not some other function), the second version would be preferred (though you could
still match in the first version to create a block in main where `FilePath` is statically defined). Pretty arbitrary though.