Oriel Jutty 

@barubary@infosec.exchange
200 Followers
56 Following
7.2K Posts
Indoor European. I know #regex. I write #code (in #C or #Haskell or #Perl or #JavaScript or #bash). 100% OPSEC.
:qExit vim
Verifiedhttps://infosec.exchange/@barubary
Pronounshe, his, him, him
New from 404 Media: the Signal clone the Trump administration uses was just hacked. TeleMessage makes a modified version of Signal that archives messages for government agencies, Waltz used it. A hacker got some users' messages, group chats. Hugely significant breach https://www.404media.co/the-signal-clone-the-trump-admin-uses-was-hacked/
The Signal Clone the Trump Admin Uses Was Hacked

TeleMessage, a company that makes a modified version of Signal that archives messages for government agencies, was hacked.

404 Media

@rzeta0

for now my understanding is that the list comprehension is the mechanism for creating all the "combinations" which are then used by liftA2 and the in turn by filterM

This is correct.

In older versions of the standard library, filterM was defined in terms of Monad, not Applicative, so it probably used liftM2, not liftA2. But in the end, that boils down to >>=, which for lists is just flip concatMap, and list comprehensions like [(x, y) | x <- xs, y <- ys] can always be written in terms of concatMap: flip concatMap xs (\x -> flip concatMap ys (\y -> [(x, y)]))

TMTOWTDI, etc

@BoydStephenSmithJr I just had an awful idea:

f2 acc x = do
l <- get
unless (elem x l)
put (x : l)
l2 <- get
return (acc + l2 - l)

😦

I'm getting really tired of alt-text entry UI just assuming you can remember multiple lines of text and enter it perfectly.

Some of us have brains that don't work, put the text entry NEXT TO the image, not on top of it!

@rzeta0 In concrete terms, you have to look at the definition of filterM, which is apparently:

filterM p = foldr (\ x -> liftA2 (\ flg -> if flg then (x:) else id) (p x)) (pure [])

It is defined in terms of liftA2 and pure, which for lists are defined as:

pure x = [x]
liftA2 f xs ys = [f x y | x <- xs, y <- ys]

Also, for didactic reasons, let's restore the second parameter of the function passed to liftA2:

(\flg -> if flg then (x:) else id)
-- eta
(\flg rest -> if flg then x : rest else rest)

... and the one passed to foldr, too:

(\ x -> liftA2 (...) (p x))
-- eta
(\x z -> liftA2 (...) (p x) z)

Putting it all together gives

pure x = [x]
liftA2 f xs ys = [f x y | x <- xs, y <- ys]
filterM p = foldr (\x z -> liftA2 (\flg rest -> if flg then x : rest else rest) (p x) z) (pure [])

and after inlining (and renaming the conflicting variables to x' and y')

filterM p = foldr (\x z -> [(\flg rest -> if flg then x : rest else rest) x' y' | x' <- p x, y' <- z]) [[]]

and then

filterM p = foldr (\x z -> [(if x' then x : y' else y') | x' <- p x, y' <- z]) [[]]

So what's going on here? We're using foldr to transform an input list into an output list (more specifically, into an output list of lists, i.e. [a] -> [[a]]). Our "accumulator", the z parameter of the function, is a list of possible tails generated so far (or tails that will be generated in the future, depending on how you look at it). Initially, the list of possible tails only has one element: the empty list ([[]]).

p x is our predicate p applied to the current element x. In the (\x -> [True, False]) example, x is ignored and p x is always [True, False].

Using this nested list comprehension, we iterate over all possible predicate values (i.e. [True, False] in this case) and all possible list tails z, and then either prepend the current element x to the current tail y' (x : y') or not (y'), i.e. either include x in the output list or not.

@rzeta0 In a very handwavy way, the [] monad represents multiple universes. So if you have x = [1,2,3], you can think of it as a combination of universes, one where x = 1, one where x = 2, and one where x = 3. The monadic operations on [] let you write code that looks like it only deals with single values (runs in a single universe), but it automatically produces a list of all possible results.

In that interpretation, [True, False] is a multiverse of conditions, with one universe where the condition is True and one where it is False. Hence the filter condition (\x -> [True, False]) says to both include and exclude x from the list of results, and since filterM is "monad aware", it then produces a list of all possible universes (i.e. one where all elements are included, one where all elements are excluded, and everything in between).

@q Last time I looked, their documentation handled that really badly. They took the list of function names, sorted it, then translated it (instead of sorting it after translating). So e.g. ZEICHEN is somewhere near the beginning of the list because CHAR starts with a C.
There are three hard problems in distributed systems:
2. Exactly-once message delivery
1. Message ordering
2. Exactly-once message delivery
2. Exactly-once message delivery
2. Exactly-once message delivery
2. Exactly-once message delivery
2. Exactly-once message delivery
@fl @abuseofnotation I refer you to section "9.3 Further Functions" on page 134 of the "LISP I Programmer's Manual", 1960.

saw a link to an open-source project with ā€œAI-powered compilationā€ and i looked at the code out of morbid curiosity

this was in the diff to their Cursor config file

anyway, brb, i’m going to go yell ā€œDO NOT burn!!!ā€ at the pizza that i’ve had in the oven for the past 3 hours. i’m sure that’ll help