Hi, On Sun Feb 12, 2023 at 10:47 AM GMT, Christopher Baines wrote: > I think there's some room to improve the introduction here. Linking to > the previous post in the series is fine, but what I think is missing is > some context around the topic and setting some expectations for the > reader. > I'm not sure who you're pitching this post at People who have used Guix and know basic Scheme but haven't delved into Guix's interiors yet :) > I think the s's after the `#f` and `'()` here don't aid > readability. Something like: Fair. > I think it would be clearer to say "To define the maybe monad, we use > the define-monad macro.", then there's no need to keep track of what API > is being discussed. I'm also not sure it's useful to talk about things > within Guix as APIs unless you're talking about a specific case of using > Guix from some external program/software. Good point. Maybe I could say something like: "To define the maybe monad's behaviour, we use the define-monad macro." using "behaviour" to describe the specifics of a monad. > I think this would be confusing for someone who's encountering monads > for the first time. I think it's good to try and avoid going to deep, > but if there's mention of the "laws", I think it's important to say that > these laws come from category theory. Yeah, okay. > > + > > +```scheme > > +(mbegin %maybe-monad > > + (remove-a "abc")) > > +;; #< is?: #t value: "bc"> > > +``` > > This is stretching my understanding of monads here, but would this > example be better if the (mbegin bit included two expressions rather > than one? I might just remove the MBEGIN example entirely. I have no idea why MBEGIN exists, or what advantages it confers, so I just included it for the sake of completeness -.o.- If someone could elaborate on what MBEGIN is for I would very much appreciate it. > I think the point is still good here, but maybe it's simpler to say "but > why does Guix use monads?". Okay. > > +So, when we do `(run-with-state result (list 32))`, we're passing `(list 32)` as > > +the initial state value, and then the `>>=` form passes that and `33` to > > +`state-push`. What `%state-monad` allows us to do is thread together some > > +procedures that require some kind of state, while pretending the state isn't > > +there, and then retrieve both the final state and the result at the end! > > I'm not sure the "pretending the state isn't there" but is helpful here, > if you're pretending the state doesn't exist, why is writing monadic > code helpful? Yeah, this doesn't really get across the point I'm trying to make. I'm not sure how else to word it, though... > > +We mentioned that, technically, we didn't need monads for Guix. Indeed, many > > +(now deprecated) procedures take a store value as the argument, such as > > +`build-expression->derivation`. However, using monads both helps ensure purity > > +and simply looks nicer. > > I'm not sure what you mean by purity here? Me neither :P Simon mentioned something about monads ensuring purity in their review, which I didn't quite understand, so I just wrote something vague about it (which I shouldn't have done). > > +And indeed, it symlinks the `irssi` binary to the output path. Some other, > > +higher-level, monadic procedures include `interned-file`, which copies a file > > +from outside the store into it, and `text-file`, which copies some text into it. > > +Generally, these procedures aren't used, as there are higher-level procedures > > +that perform similar functions (which we will discuss later), but for the sake > > +of this blog post, here's an example: > > + > > +```scheme > > +(with-store store > > + (run-with-store store > > + (text-file "unmatched-paren" > > + "( "))) > > +;; "/gnu/store/v6smacxvdk4yvaa3s3wmd54lixn1dp3y-unmatched-paren" > > +``` > > I think the build up to this section is pretty good, but then I'm not > sure what this last section is trying to explain. It's just showing an example of the TEXT-FILE procedure, that's all :) > Maybe at this point it would be good to leave the REPL and give some > concrete examples of non-trivial monadic code in Guix, and discuss what > that would look like if implemented without using monads. Good idea! :) > > +# Conclusion > > + > > +What have we learned about monads? The key points we can take away are: > > + > > +1. Monads are a way of composing together procedures and values that are wrapped > > + in containers that give them extra context, like `maybe` values. > > +2. Guix provides a high-level monad API that compensates for Guile's lack of > > + strong types or an interface-like system. > > I'd say that Guile is a strongly typed language. I'm also not sure what > the point about compensating for something lacking in Guile means. Guile doesn't have type definitions and it can't "fix" values to types. I'd consider that to be weak typing, personally :) Regarding the point: it's supposed to say something like > > +4. Guix uses the store monad frequently to thread a store connection through > > + procedures that need it. > > +5. The store monad is really just the state monad in disguise, where the state > > + value is used to thread the store object through monadic procedures. > > 4 and 5 here are observations, but not very useful conclusions. I think > the more interesting question to ask is why are things implemented this > way? > Ideally the closing points would be well made in the previous section, > and this final bit would be a summary. They're supposed to be a short summary of the main lessons the blog post attempts to teach, but I'll consider removing them. > > +If you've read this post in its entirety but still don't yet quite get it, don't > > +worry. Try to modify and tinker about with the examples, and hopefully it will > > +all click eventually! > > Maybe this could be a call to get involved in the community (talk on IRC > or the mailing list? Yeah, good idea :) -- (