Skip to content

Instantly share code, notes, and snippets.

@mpickering
Created August 19, 2014 10:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mpickering/f74e1f5cbd15084c6ea8 to your computer and use it in GitHub Desktop.
Save mpickering/f74e1f5cbd15084c6ea8 to your computer and use it in GitHub Desktop.
Transclusion

This is the extra file.

{-# LANGUAGE DeriveFunctor #-}
import Control.Monad.Free
import Text.Parsec hiding ((<|>), many)
import Control.Applicative
import Control.Monad.Trans
-- All impure effects are abstracted to a data type, it can be extended as
-- new impure effects are needed.
data ImpureF a = ReadFile FilePath (String -> a) deriving Functor
type Impure = Free ImpureF
include :: FilePath -> Impure String
include fp = liftF $ ReadFile fp id
-- If running in IO, we can perform impure effects
run :: Impure a -> IO a
run (Pure r) = return r
run (Free (ReadFile fp f)) = readFile fp >>= run . f
-- If in a pure setting we can't process includes
runPure :: Impure a -> a
runPure (Pure r) = r
runPure (Free (ReadFile _ f)) = runPure $ f ""
md = "This is a markdown file with an \n {extrafile.md} which should be inserted in the middle"
data AST = Word String deriving (Show)
-- We place the impure free monad at the bottom of the stack
mdparser :: ParsecT String () Impure [AST]
mdparser = many (try includemd <|> word)
includemd = do
char '{'
fname <- manyTill anyChar (char '}')
conts <- lift $ include fname
return (Word conts)
word = Word <$> (spaces *> (many1 (noneOf " ")) <* spaces)
getRight (Right x) = x
main :: IO ()
main = do
let inp = runParserT mdparser () "" md
putStrLn "pure"
putStrLn . show $ getRight (runPure inp)
putStrLn "impure"
putStrLn . show . getRight =<< run inp
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment