Last active
June 24, 2016 16:57
-
-
Save aaronlevin/d798df06bd303f767a81 to your computer and use it in GitHub Desktop.
Adventures in Point-Free, Arrowized Absurdity
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- | check for parens in a string, exiting early if the left paren count is -1. Fully point-free and | |
-- arrow-fied | |
-- It works as follows: | |
-- 1. use a monadic fold (foldM) with the Either monad to exit early | |
-- 2. take a list of methods that test if the count is -1, or the paren is '(', or the paren is ')' | |
-- 3. zip the list with another list that looks at the booleans and decides what functions they should | |
-- result in. if there are no parens, the functions just add 0 to the count | |
-- 4. sequence the monad actions (this will exit early if there is a Left present) | |
-- 5. fold over the functions in the Right branch with function composition | |
-- 6. at this piont we just want to apply the the resulting function in the Right branch to the current | |
-- count. this was *really* hard in point-free for, hence the &&& fst >>> second (fmap . flip ($)) | |
-- tomfoolery. it took me an embarrassingly long time to figure this out :( | |
-- 7. when the foldM is finished, we have `False` if there is a `Left` and we check that the left paren | |
-- count is `0` on the right. | |
-- | |
-- >>> checkParens "hello" | |
-- True | |
-- >>> checkParens "he(llo" | |
-- False | |
-- >>> checkParens "he(ll)o" | |
-- True | |
-- >>> checkParens "h)e(ll)o" | |
-- False | |
checkParens :: String -> Bool | |
checkParens = either (const False) (== 0) . foldM go 0 | |
where | |
go = curry $ ( sequence [(== -1) . fst, (== '(') . snd, (== ')') . snd] | |
>>> zipWith (bool . Right $ (+ 0)) [Left (), Right (+ 1), Right (flip (-) 1)] | |
>>> sequence | |
>>> (<$>) (foldl (.) id) | |
) | |
&&& fst | |
>>> second (fmap . flip ($)) | |
>>> swap | |
>>> app | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment