Skip to content

Instantly share code, notes, and snippets.

@ahaxu
Last active June 5, 2023 03:05
Show Gist options
  • Save ahaxu/a0cc290dbe14521e97c7e515c4f6e66c to your computer and use it in GitHub Desktop.
Save ahaxu/a0cc290dbe14521e97c7e515c4f6e66c to your computer and use it in GitHub Desktop.
distinctG.hs
-- Link to youtube https://youtu.be/c4saFSUAmlg
-- | Remove all duplicate integers from a list. Produce a log as you go.
-- If there is an element above 100, then abort the entire computation and produce no result.
-- However, always keep a log. If you abort the computation, produce a log with the value,
-- "aborting > 100: " followed by the value that caused it.
-- If you see an even number, produce a log message, "even number: " followed by the even number.
-- Other numbers produce no log message.
--
-- /Tip:/ Use `filtering` and `StateT` over (`OptionalT` over `Logger` with a @Data.Set#Set@).
--
-- >>> distinctG $ listh [1,2,3,2,6]
-- Logger ["even number: 2","even number: 2","even number: 6"] (Full [1,2,3,6])
--
-- >>> distinctG $ listh [1,2,3,2,6,106]
-- Logger ["even number: 2","even number: 2","even number: 6","aborting > 100: 106"] Empty
distinctG ::
(Integral a, Show a) =>
List a
-> Logger Chars (Optional (List a))
--filtering ::
-- Applicative k =>
-- (a -> k Bool) -- StateT Set OptionalT (Logger Chars Optional (Bool, Set))
-- -> List a
-- -> k (List a) -- StateT Set OptionalT (Logger Chars Optional ((List a), Set))
distinctG as =
let
rs = filtering
(\a -> StateT $ \s -> OptionalT $
if a > 100
then log1 ("aborting > 100: " ++ show' a) Empty
else
if even a
then
log1 ("even number: " ++ show' a) (if S.notMember a s then Full(True, S.insert a s) else Full(False, s))
else
pure (if S.notMember a s then Full(True, S.insert a s) else Full(False, s))
)
as
x = runOptionalT $ evalT rs S.empty
in x
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment