Even better. How would you go about finding the source code containing the definition of the function `D.subExpressions` ?
> What does Optics.rewriteOf do?
Hoogling show this is an alias of https://hackage.haskell.org/package/lens-5.1.1/docs/Control-....
> What's the purpose of Lint.useToMap?
Hoogle again shows https://hackage.haskell.org/package/dhall-1.41.1/docs/Dhall-.... If your function is not indexed you can look at what is qualified as `Lint` and look it up that way.
> How about D.subExpressions ? How does that composition work with the loop function?
https://hackage.haskell.org/package/dhall-1.41.1/docs/Dhall-... All nicely documented... I'm not sure what you mean by composition with the loop function. First the loop function is executed and then afterwards over the result the expression in the first argument to fmap is applied. There is no weird interaction going on here. It's just run this over the result of the loop function if it didn't produce an error.
> Even better. How would you go about finding the source code containing the definition of the function `D.subExpressions` ?
Use hoogle or just look at the imports at the top of the file. Just like any other programming language. Or even better, use the language server to find it for you. For example there is an import here:
`import qualified Dhall.Core as D`
Now you know that function is in the `Dhal.Core` module. Going to that module you see the function is not actually there but is exported from the `Dhal.Syntax` module. It took me literally 5 seconds to find it: https://github.com/dhall-lang/dhall-haskell/blob/master/dhal...
That explains nothing? What does it do? How does it do it? What do the type variables `a b a b` mean? Why are there 4 of them? What is ASetter?
https://hackage.haskell.org/package/lens-5.1.1/docs/Control-...
Absolutely nothing explained whatsoever. Yup, sounds like like the typical, familiar Haskell experience of zero useful docs where you need them.
I use the lens library all the time and those docs make perfect sense, particularly if you apply just the teensiest bit of logic and thing “Could a setter, perhaps, set something?”. It’s a DSL, and you don’t understand the domain - I’m sure you’d have a great time explaining this function from LLVM without referring to any other part of the documentation to give it context https://llvm.org/doxygen/group__LLVMCCoreValueInstructionGet.... What’s a GEP? Under the rules you’re applying to the lens documentation, I’m not allowed to look that up, because it should be immediately obvious.
> Get the source element type of the given GEP operator
Notice the relentness repetition that provides precision and clarity? I now know the argument GEP is a GEP operator. Might seem redundant, but it allows a new reader to start from any point and find their way to the relevant terms / nouns and their types.
All within reach within seconds of discovering the function. To understand any tool you must understand the libraries and tools it to some degree. Your questions here are not Haskell specific, and the answers to the question you asked are easy to find. I'm not familiar with the Dhall code base and was able to answer you within minutes.
Its not within any reach whatsoever. The overview isn't linked anywhere in Setter.
Rule of writing documentation: if you're not going to write anything useful in the docs from a user perspective, don't pretend to write any docs at all.
Oh, and also, that link you posted still doesn't answer what does `rewriteOf` actually do.
Going back to the original docs of rewriteOf (https://hackage.haskell.org/package/lens-5.1.1/docs/Control-...)
> Rewrite by applying a rule everywhere you can
Rewrite what? In what? By applying what rule? Which type is the type being rewritten here? Which type is the rule? Completely unclear. This is not how you write library documentation, at all. Tutorials and overviews won't cut it - you need clear API docs, which are written by providing unabiguous explanation of the function inputs, function outputs and how they relate to each other.
(Yes, this is tedious and yes it often involves repetition, but it means a ton for actual library usability)
If there was one recommendation I could give to all Haskell library authors, it would be to explicitly assign an unabiguious descriptive alias noun to every argument within the text that describes their function. In the `rewriteOf` case, that would look something like this:
> Rewrite the type (insert type found in the argument list here) by applying the rule (insert type of the rule in the argument list) everywhere you can.
_1 :: Lens' (a,b) a
is used immediately after set :: Lens' a b -> b -> a -> a
which completely messes with anyone who's mind works in a way that makes it extremely difficult when symbols are immediately reused with completely different meanings.To summarize, Haskell documentation communication is biased against linguistically clear explanations and towards mathematically precise, symbolic "explanation", and those who are used to unnecessarily struggling with the latter style due to their math background are more likely to "make it".
Yes its confusing. It sometimes helps to give longer variables:
_1 :: Lens' (fst, snd) fst
set :: Lens' structure focus -> focus -> structure -> structure
set _1 :: fst -> (fst, snd) -> (fst, snd)
You are bumping up against the severe amount of polymorphism at play in the lens library. This makes it hard to build a mental model but is a tremendous source of expressiveness and utility.Right... Like the doc of the regex match function in Rust is useless because it doesn't explain regexes. https://docs.rs/regex/latest/regex/struct.Match.html
Or the C# beginSocketfunction because it doesn't explain what TCP is. https://docs.microsoft.com/en-us/dotnet/api/system.net.socke...
Or the go Exec function in the sql package not explaining with SQL or databases are. https://pkg.go.dev/database/sql#DB.Exec
Any function level documentation expects you to know the basics and the contexts of a library. Documentation on that level is most certainly not useless. It's the standard in every language, for every library. I don't feel like you are approaching this from a fair point of view so I will stop replying. Can't convince people who don't want to be convinced.
You asked what's wrong, I assumed you'd like to know what I think. To me it now looks like you wanted to prove me wrong instead.
I summarized plenty of problems, with the biggest one being bad API docs due to lack of detailed arguments and return types description and labeling and bad naming practices in general.
FWIW, I've watched 4 hours worth of video on Haskell lens by SPJ and I still don't find the documentation clear. It could simply be that I'm not clever enough. Well written API docs would definitely help with that too though.
https://hackage.haskell.org/package/optics-0.1/docs/Optics.h...
At least they name their type variables:
> The lifetime parameter 't refers to the lifetime of the matched text
C# do too: https://docs.microsoft.com/en-us/dotnet/api/system.net.socke... - every function argument is named, labelled and described separately.
You are complaining that a single function within a library doesn’t describe the whole abstraction the library is built on? Should every single function, operator and type include the whole fucking lens tutorial so you don’t have to go and find it?
I suppose every web library should include an explanation of IP, TCP, UDP, HTTPS, url encoding, compression and anything else that is needed, on every single function too? Christ, I cannot believe how incredibly dumb your take here is. Libraries in every single language provide some kind of preamble in their documentation which covers what abstraction that library provides, and Haskell is no different; the particular library you have chosen to misunderstand is INCREDIBLY general, the documentation is actually amazingly precise, if you have taken the time to learn what an optic is.
I genuinely think you should be ashamed of this opinion, because it shows that you’re both willingly ignorant, and proud to state that fact publicly.
> Those type variables CAN’T be named anything better because they could be absolutely anything at all, that’s the point of generic types.
I was talking about the word "rule" and the verb "rewrite", and was explaining how the Rust documentation is explicit what is what (The type variable 'a refers to <X>). Similarly, the docs here can be explicit about which part is the rule and which part is the thing being rewritten.
I don't like guessing, but I will try and guess which thing refers to which and try to rewrite the doc myself
> ASetter a b a b -> (b -> Maybe a) -> a -> bSource
> Rewrite (ASetter a b a b) by applying the rule (b -> Maybe a) everywhere it can be i.e. everywhere the function returns `Just a`.
Now, for this part
> Ensures that the rule cannot be applied anywhere in the result:
> propRewriteOf l r x = all (isNothing . r) (universeOf l (rewriteOf l r x))
I would hazard a guess to try and translate that to
Ensures that the rule cannot be applied anywhere where the rule function returns `Nothing`
Did I get these right? Hell if I know. Maybe the Setter is the rule. Maybe that `universe` crap means something else, because sure, the best way to document a function is to describe it with code using yet another poorly documented function (not).
Why are you so defensive? Are haskellers incapable of learning from any negative feedback?
Am I willfully ignorant by pointing out how the documentation can be improved, and by giving examples how other languages take the approach I'm describing? Well written library documentation describes all input and output types explicitly. That's it, thats my claim. Do you contest that claim? Is it impossible to specify which part of that type is a rule and which part is the thing being rewritten, in the docs? Why? Do you think that's good documentation practice?
To answer your questions explicitly
> You are complaining that a single function within a library doesn’t describe the whole abstraction the library is built on?
No, I ask that the documentation describe which nouns refer to which parts of the type
> Should every single function, operator and type include the whole fucking lens tutorial so you don’t have to go and find it?
No, they should include enough description to know what every part of the type refers to in the documentation text.
> I suppose every web library should include an explanation of IP, TCP, UDP, HTTPS, url encoding, compression and anything else that is needed, on every single function too?
No, but it should explicitly state which part of its arguments refers to which concept (IP address, URL, etc), except perhaps when the argument name contains a reference to that concept and the name is clearly visible in the documentation
> Christ, I cannot believe how incredibly dumb your take here is.
Did you actually read my take, or did you knee-jerk into the typical "OMG YOU CAN'T DESCRIBE TYPE ARGUMENTS THEY'RE ABSTRACT" reaction? Yes, I know those types don't have meaning outside of a context. No, that is not what I was asking. (Although, poorly named positional type arguments are pretty dumb, but thats a story for a different day)
> Libraries in every single language provide some kind of preamble in their documentation which covers what abstraction that library provides, and Haskell is no different
They also make the connection between the argument types and the nouns used in the documentation. Something that is made more difficult in Haskell because the argument names are omitted from the generated documentation and often poorly written.
> the particular library you have chosen to misunderstand is INCREDIBLY general, the documentation is actually amazingly precise, if you have taken the time to learn what an optic is
I've spent anywhere between 6-12 hours on lens tutorial and optics, 4 of which on the SPJ videos. Doesn't make this documentation more clear, however. Please, do tell me how dumb I am. I'm totally listening, because thats how you are supposed to react when someone provides feedback.
> I genuinely think you should be ashamed of this opinion, because it shows that you’re both willingly ignorant, and proud to state that fact publicly.
Please take a step back, and read again what I propose with an open mind. Don't take the criticism as a personal attack.
I honestly did my best to describe what I believe is wrong with the whole Haskell documentation culture, because someone asked. I haven't seen anything here to change my mind.
{-| Given `Conversion` options and a Dhall type `ExprX`,
try to convert the JSON value `Value` to a Dhall expression of the specified type.
Additionally, if the conversion is successful, apply a rewrite on all maps in the key-value map pair format to map nodes
(i.e. `[{ mapKey = "foo", mapValue = 1 }] -> toMap {foo = 1}`) -}
And here is how I would decompose the first part dhallFromJSON (Conversion {..}) expressionType value = do
let normalizedType = D.alphaNormalize (D.normalize expressionType)
dhallExpression <- loop [] normalizedType value
-- Rewrite maps
return $ Optics.rewriteOf D.subExpressions Lint.useToMap dhallExpression