Did your function just mod the state?
Context
In Emacs lisp
shell-command-to-string function in Emacs is not a pure function, because it has side effects,
such as executing a shell command and potentially altering the state of the system.
In contrast, adding to the exec-path is considered an impure function since. it modifies the
environment by changing the list of directories where Emacs looks for executable files.
This post ll also observe the interopeability aspect1
Deffered exec of Emacs lisp
Macros vs lazy eval
defmacro defines Lisp macros that transform and generate code at compile time or before evaluation.It operates on the unevaluated code expressions (arguments as code), rewriting them into new Lisp expressions that get evaluated later. This allows defining new syntactic constructs and control over evaluation order.
Lazy evaluation means delaying the evaluation of expressions until their values are actually needed at runtime. Lazy evaluation controls when an expression is computed to avoid unnecessary work but does not transform or rewrite the code itself. Caveat : The error don’t trying to splice whole keyword argument lists directly in a backquoted use-package form, which produces invalid syntax for the macro expansion. The correct approach is to build and combine the argument list first, then call use-package via apply.
Lisp macro rwrites vs Haskell’s automatic derivation
In Haskell, automatic derivation is a type-system feature that automatically generates instances of certain type classes (like Eq, Show, Ord) for data types based on their structure. This happens at compile time, producing boilerplate code so programmers don’t have to write repetitive instance declarations. It relies on Haskell019s strong static type system and compiler extensions.
Lisp’s defmacro defines a macro that transforms Lisp code before evaluation. Macros in Lisp manipulate code as data (unevaluated s-expressions) and can generate new code with arbitrary complexity, enabling metaprogramming and custom syntactic constructs. defmacro works at the syntactic level producing new Lisp expressions.
In Haskell
The analogy needed sufficient context. So, I wrote a masto client app running on warp server, with a single feature to post a toot to my instance from localhost,
separation of concerns between warp and masto servers
wai warp side is already written
Reads registed client creds from OS store tool and stores them in Appstate, not
DATABASEwhich is loaded to hte warp server instance as the server starts to recive and send http (get,post) requests to masto server Wai app , recieves auth details request from masto server, handles them and responds to them with html forms, text inputs from user, does the due jason parsin of assii string text manipulation , these responses are sent back to masto severMasto server
Upon receinving any of these requests, verifies if its a credential, sends back the http response over TLS and wai, routes and loads them accordingly.
Note on data manipulation 👁️
I and concatinating TEXT in my HTML with Data.ByteString.Lazy, which provides a way to
handle large or unbounded streams of data efficiently in Haskell, while
Data.ByteString.Lazy.Char8 offers a character-based interface for manipulating lazy ByteString
s, specifically for 8-bit characters. Both are useful for different tasks, with the former
focusing on general byte manipulation and the latter on character operations, making them
suitable for tasks like handling ASCII and HTML data
Notes On record field, values,
In Haskell, when you declare a record like:
haskell
data ApiClient = ApiClient
{ acMastodonInstance :: String
-- other fields
}the name acMastodonInstance is a function of type: acMastodonInstance::ApiClient → String acMastodonInstance::ApiClient → String
It needs to be applied to a value of type ApiClient (an instance) to obtain the String. That’s why you ough to supply a value of type ApiClient for the field accessor acMastodonInstance to produce a String.
function application and Lambda Calculus
when you ve instantiated this data consturctor record field as its value , say client and you apply a function to it as
Namespace pollution or ambiguity, Which functions can’t be exported from an imported module.
Tell me to use liftIO for lessr runtime penaly
Associative concat for html strs, even applicative style, Monadic chaining or newtype when I wrote pure functions 2 for > one type of data, or liftIO to reduuce runtime penaly in some cases and hls code-completion
code for callback routing uses both function binding and pattern match on MayBe with case , and I am using WAI app interface for make it work, while I don’t get dsl of servant etc for decrataive code, I do get to isolate my logic here , which as critical as separation of concerns.
So it also illustrates how a beginner can start with just case, just conditionals , MayBe Monad and pattern match and advance towards higher concepts with ormolu and idk manual or search. Beware of AI though , there are case when even ormolu can throw you in chicken and egg loop of errors in just one block and AI ll fail to resolve it, instead of being lost in patterns or some textbooks papers, which dont tell you which tooling to you for good.
Here s the working programs for the above, but do check the prev commit for the boilerplate simpler code if you re learning.
*
Footnotes
https://academy.fpblock.com/blog/rust-haskell-reflections/↩︎
If you wrote any nix, this is like thos configuration files, which re also pure with worse or no typecheck, till , you insist that to built it, idk, in some impure way. It also means that my src does not need to access the record fields at compile time, and I should not get “unused fields” warnings, if I set up warp correctly
- Define record with server satte
- IO action for runtime access to fiels ie loading the record fields
these parts are already there?
- Define server app which takes server state or it’s loading as an argument
- A main function to tie everything