Skip to content

Instantly share code, notes, and snippets.

@masaeedu
Last active July 4, 2019 18:52
Show Gist options
  • Select an option

  • Save masaeedu/d391fb8d7d4da8bb7473fe833a6a8c7f to your computer and use it in GitHub Desktop.

Select an option

Save masaeedu/d391fb8d7d4da8bb7473fe833a6a8c7f to your computer and use it in GitHub Desktop.
Comonad on a Kleisli category
module ComonadKleisli where
import Data.Maybe
import Data.List
import Control.Monad
fmapM :: (a -> Maybe b) -> [a] -> Maybe [b]
fmapM f = Just . catMaybes . fmap f
duplicateM :: [a] -> Maybe [[a]]
duplicateM = pure . tails
extractM :: [a] -> Maybe a
extractM = listToMaybe
-- Comonad laws:
-- - extractM <=< duplicateM = pure
-- - fmapM extractM <=< duplicateM = pure
-- - duplicateM <=< duplicateM = fmapM duplicateM <=< duplicateM
extendM :: ([a] -> Maybe b) -> [a] -> Maybe [b]
extendM f = fmapM f <=< duplicateM
isHeader :: String -> Bool
isHeader ('#' : _) = True
isHeader _ = False
test :: [String] -> Maybe [[String]]
test = extendM $ \l -> do
(h, xs) <- uncons l
if isHeader h
then Just $ h : takeWhile (not . isHeader) xs
else Nothing
main :: IO ()
main = do
print $ test ["# header", "text", "more text", "# header 2", "some text"]
-- Just [["# header","text","more text"],["# header 2","some text"]]
print $ test []
-- Just []
print $ test ["foo", "bar", "# header", "baz"]
-- Just [["# header","baz"]]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment