:q | Exit vim |
Verified | https://infosec.exchange/@barubary |
Pronouns | he, his, him, him |
:q | Exit vim |
Verified | https://infosec.exchange/@barubary |
Pronouns | he, his, him, him |
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).
ZEICHEN
is somewhere near the beginning of the list because CHAR
starts with a C.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