hatex-guide 1.1.0.0 → 1.2.0.0
raw patch · 12 files changed
+295/−39 lines, 12 filesdep +blaze-htmldep +timedep +transformersPVP ok
version bump matches the API change (PVP)
Dependencies added: blaze-html, time, transformers
API changes (from Hackage documentation)
+ Text.LaTeX.Guide: HTML :: Backend
Files
- README.md +5/−1
- Text/LaTeX/Guide.hs +2/−0
- Text/LaTeX/Guide/Auto.hs +1/−1
- Text/LaTeX/Guide/Backend/HTML.hs +171/−0
- Text/LaTeX/Guide/Backend/LaTeX.hs +1/−1
- Text/LaTeX/Guide/Backend/Wiki.hs +4/−8
- Text/LaTeX/Guide/Info.hs +1/−1
- Text/LaTeX/Guide/Syntax.hs +45/−20
- hatex-guide.cabal +9/−7
- src/basics.htxg +19/−0
- src/monad.htxg +33/−0
- src/packages.htxg +4/−0
README.md view
@@ -5,13 +5,17 @@ A pdf version (created from the LaTeX output) can be downloaded from [here](http://daniel-diaz.github.com/projects/hatex/hatex-guide.pdf). +An online version (created from the HTML output) can be seen+[here](http://daniel-diaz.github.com/projects/hatex/hatex-guide.html).+ # Building the guide To build the guide, first you need to install the library. ## Installing from Hackage -Using _cabal-install_ you can install the library directly from Hackage.+Using _cabal-install_ you can install the library directly from+[Hackage](http://hackage.haskell.org/package/hatex-guide). $ cabal install hatex-guide
Text/LaTeX/Guide.hs view
@@ -29,9 +29,11 @@ import Text.LaTeX.Guide.Update import qualified Text.LaTeX.Guide.Backend.LaTeX as LaTeX import qualified Text.LaTeX.Guide.Backend.Wiki as Wiki+import qualified Text.LaTeX.Guide.Backend.HTML as HTML -- | Write in the current directory the LaTeX User's Guide using -- a determined backend. writeGuide :: Backend -> IO () writeGuide LaTeX = LaTeX.backend writeGuide Wiki = Wiki.backend+writeGuide HTML = HTML.backend
Text/LaTeX/Guide/Auto.hs view
@@ -7,4 +7,4 @@ -- | The version of the guide. Based on the version of the package. guideVersion :: Version-guideVersion = Version [1,1,0,0] []+guideVersion = Version [1,2,0,0] []
+ Text/LaTeX/Guide/Backend/HTML.hs view
@@ -0,0 +1,171 @@++{-# LANGUAGE OverloadedStrings #-}++module Text.LaTeX.Guide.Backend.HTML (+ backend+ ) where++import Text.LaTeX.Guide.Syntax+import Text.LaTeX.Guide.Info hiding (LaTeX)+import Text.LaTeX.Guide.Auto+--+import Text.Blaze.Html5 (Html,toHtml,preEscapedToHtml,preEscapedToValue,(!))+import qualified Text.Blaze.Html5 as H+import qualified Text.Blaze.Html5.Attributes as A+import Text.Blaze.Html.Renderer.Text (renderHtml)+import Data.Text.Lazy.IO+--+import Data.Monoid+import Control.Monad.Trans.State+import Control.Applicative ((<$>))+import Data.List (intersperse)+import Data.Version (showVersion)+-- Time+import Data.Time++resURL :: Text -> Text+resURL t = "https://raw.github.com/Daniel-Diaz/hatex-guide/master/res/" <> t++sectFromInt :: Int -> Html -> Html+sectFromInt 1 = H.h1+sectFromInt 2 = H.h2+sectFromInt 3 = H.h3+sectFromInt 4 = H.h4+sectFromInt 5 = H.h5+sectFromInt 6 = H.h6+sectFromInt n = error $ "Subsection with hierarchy of " ++ show n ++ " is not available in the HTML backend."++type SectionNumber = [Int]++showSN :: SectionNumber -> String+showSN = mconcat . intersperse "." . fmap show++mapLast :: (a -> a) -> [a] -> [a]+mapLast _ [] = []+mapLast f [x] = [f x]+mapLast f (x:xs) = x : mapLast f xs++upgradeSN :: Int -> SectionNumber -> SectionNumber+upgradeSN n [] = replicate (n-1) 0 ++ [1]+upgradeSN n sn = mapLast (+1) $ take n $ sn ++ repeat 0++sectiondots :: Int -> Html+sectiondots 1 = mempty+sectiondots n = toHtml $ (mconcat $ replicate (n-1) str) ++ " "+ where+ str :: String+ str = ".........."++data HtmlState =+ HState { fnIndex :: Int -- Footnote index+ , sectionNumber :: SectionNumber -- Section numbering+ , htmlBody :: Html -- HTML body+ , fnHtml :: Html -- Footnotes html+ , tocHtml :: Html -- Table Of Contents+ }++defaultState :: HtmlState+defaultState = HState 1 [] mempty mempty mempty++type HtmlM = State HtmlState++ihtml :: Html -> HtmlM ()+ihtml h = modify $ \s -> s { htmlBody = htmlBody s <> h }++ihtmlf :: (Html -> Html) -> HtmlM () -> HtmlM ()+ihtmlf f hm = do+ s0 <- get+ let s1 = execState hm $ s0 { htmlBody = mempty }+ put $ s1 { htmlBody = htmlBody s0 <> f (htmlBody s1) }++execHtmlM :: HtmlM a -> Html+execHtmlM hm =+ do let s = execState hm defaultState+ H.h1 "Table of contents"+ tocHtml s+ H.br+ H.a ! A.href "#footnotes" $ "Footnotes"+ H.hr+ htmlBody s+ H.hr+ H.a ! A.id "footnotes" $ H.h1 "Footnotes"+ fnHtml s++htmlSyntax :: Syntax -> HtmlM ()+htmlSyntax (Raw t) = ihtml $ toHtml t+htmlSyntax (Section n s) = do+ t <- sectionNumber <$> get+ let t' = upgradeSN n t+ a = "s" ++ showSN t'+ ihtmlf (sectFromInt n . (H.a ! A.id (preEscapedToValue a))) $ do+ ihtml $ toHtml $ (++". ") $ showSN t'+ htmlSyntax s+ let fortoc = do+ sectiondots n+ H.a ! A.href (preEscapedToValue $ '#' : a) $ do+ toHtml $ showSN t'+ toHtml (". " :: String)+ htmlBody $ execState (htmlSyntax s) defaultState+ modify $ \st -> st { sectionNumber = t'+ , tocHtml = tocHtml st <> H.br <> fortoc+ }+htmlSyntax (Bold s) = ihtmlf H.b $ htmlSyntax s+htmlSyntax (Italic s) = ihtmlf H.i $ htmlSyntax s+htmlSyntax (Code b t) =+ let f = if b then H.code else H.pre+ in ihtml $ f $ preEscapedToHtml t+htmlSyntax (URL t) = ihtml $ H.a ! A.href (preEscapedToValue t) $ toHtml t+htmlSyntax (IMG t) = ihtml $ H.img ! A.src (preEscapedToValue $ resURL t) ! A.width "50%"+htmlSyntax LaTeX = ihtml $ H.i "LaTeX"+htmlSyntax HaTeX = ihtml $ H.i "HaTeX"+htmlSyntax (Math t) = ihtml $ H.i $ toHtml t+htmlSyntax (Append s1 s2) = htmlSyntax s1 >> htmlSyntax s2+htmlSyntax Empty = return ()+htmlSyntax (Footnote x) = do+ s0 <- get+ let i = fnIndex s0+ str = '[' : (show i ++ "]")+ s1 = execState (htmlSyntax x) $ s0 { htmlBody = mempty }+ fn = H.p $ do H.a ! A.id (preEscapedToValue $ 'f' : show i) $ toHtml str+ toHtml (" - " :: String)+ htmlBody s1+ h = H.a ! A.href (preEscapedToValue $ "#f" ++ show i) $ toHtml str+ modify $ \s -> s { fnIndex = fnIndex s + 1+ , fnHtml = fnHtml s <> fn+ , htmlBody = htmlBody s <> h+ }+htmlSyntax (Paragraph s) = do+ ihtmlf H.p $ htmlSyntax s+ ihtml $ toHtml ("\n\n" :: String)++htmlTitle :: Day -> Html+htmlTitle d = do+ H.h1 ! A.class_ "title" $ "The HaTeX User's Guide"+ let vstr = "Version " ++ showVersion guideVersion+ H.p ! A.class_ "centered" $ H.i $ do+ toHtml vstr+ toHtml (" using " :: String)+ H.a ! A.href "http://hackage.haskell.org/package/blaze-html" $ "blaze-html"+ toHtml ("." :: String)+ H.p ! A.class_ "centered" $ H.i $ toHtml $ "Generated on " ++ showGregorian d ++ "."+ H.p ! A.class_ "centered" $ toHtml $ mconcat $ intersperse ", " $ "Daniel Díaz" : contributors++htmlConfig :: Html -> IO Html+htmlConfig h = do+ d <- utctDay <$> getCurrentTime+ return $ H.docTypeHtml $ do + H.head $ do+ H.link ! A.rel "stylesheet" ! A.href "https://rawgithub.com/Daniel-Diaz/hatex-guide/master/hatex.css"+ H.body $ htmlTitle d <> H.hr <> h++createManual :: IO Html+createManual = fmap (execHtmlM . sequence_ . fmap htmlSyntax) parseSections >>= htmlConfig++backend :: IO ()+backend = do+ Prelude.putStrLn "Creating guide..."+ m <- createManual+ Prelude.putStrLn "Writing guide file..."+ let fp = outputName ".html"+ Data.Text.Lazy.IO.writeFile fp $ renderHtml m+ Prelude.putStrLn $ "Guide written in " <> fp <> "."
Text/LaTeX/Guide/Backend/LaTeX.hs view
@@ -16,7 +16,6 @@ import Text.LaTeX.Packages.Inputenc import Text.LaTeX.Packages.AMSMath import Text.LaTeX.Packages.Babel-import Text.LaTeX.Packages.Fontenc import Text.LaTeX.Packages.Fancyhdr import Data.Version (showVersion,versionBranch) import Data.Text (unpack)@@ -49,6 +48,7 @@ hatexSyntax _ HaTeX = hatex hatexSyntax _ (Math t) = math $ raw t hatexSyntax fp (Footnote s) = footnote $ hatexSyntax fp s+hatexSyntax fp (Paragraph s) = hatexSyntax fp s <> raw "\n\n" hatexSyntax fp (Append s1 s2) = hatexSyntax fp s1 <> hatexSyntax fp s2 hatexSyntax _ Empty = mempty
Text/LaTeX/Guide/Backend/Wiki.hs view
@@ -13,12 +13,7 @@ import Data.Functor import Data.Function import Prelude (Eq (..), Num (..),IO,Monad (..), Int, uncurry, Show (..))-import Data.Maybe-import Control.Arrow-import Text.LaTeX.Base (version)-import Data.Version (showVersion) import Data.String (IsString (..))-import Data.Bool (<>) :: Monoid m => m -> m -> m (<>) = mappend@@ -55,7 +50,7 @@ in text $ f t syntaxWiki (URL t) = text t -- Images no supported.-syntaxWiki (IMG t) = mempty+syntaxWiki (IMG _) = mempty syntaxWiki LaTeX = text "LaTeX" syntaxWiki HaTeX = text "HaTeX" syntaxWiki (Math t) = text $ tag "math" t@@ -67,6 +62,7 @@ g = \n -> if n == i0 then t else f n in (i+1,g, "[[#Footnotes|" <> tag "sup" (fromString $ show i0) <> "]]") )+syntaxWiki (Paragraph s) = syntaxWiki s <> text "\n\n" syntaxWiki (Append s1 s2) = syntaxWiki s1 <> syntaxWiki s2 syntaxWiki Empty = mempty @@ -79,9 +75,9 @@ renderWiki :: Wiki -> Text renderWiki (Wiki f) = initial <> t <> foots <> ending where- (last,footf,t) = f (0 , const mempty)+ (l,footf,t) = f (0 , const mempty) foots = unlines $ "\n\n==Footnotes==\n" :- fmap (\n -> tag "sup" (fromString $ show n) <> ": " <> strip (footf n) <> "\n") [ 1 .. last ]+ fmap (\n -> tag "sup" (fromString $ show n) <> ": " <> strip (footf n) <> "\n") [ 1 .. l ] backend :: IO () backend = fmap (strip . renderWiki . syntaxWiki . mconcat . fmap (syntLineBreaks . (Raw "\n\n" <>))) parseSections >>= writeFile (outputName ".wiki")
Text/LaTeX/Guide/Info.hs view
@@ -29,7 +29,7 @@ contributors = [ ] -- | Available backends.-data Backend = LaTeX | Wiki+data Backend = LaTeX | Wiki | HTML parseSections :: IO [Syntax] parseSections = do
Text/LaTeX/Guide/Syntax.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE NoImplicitPrelude, OverloadedStrings #-}+{-# OPTIONS_GHC -fno-warn-unused-do-bind #-} module Text.LaTeX.Guide.Syntax ( Syntax (..)@@ -14,7 +15,6 @@ import Text.Parsec.Text () import Data.Text import Data.Text.IO hiding (putStr)-import Data.Monoid import Data.Int import Data.Bool import Prelude (Eq(..),Show(..),FilePath,Enum)@@ -23,12 +23,7 @@ import qualified Data.List as L import Data.Char import Data.Either-import Data.Maybe import System.IO(IO,hFlush,stdout,putStr)-import Text.LaTeX.Packages.Hyperref-import Text.LaTeX.Packages.Graphicx-import Text.LaTeX.Packages.AMSMath-import Text.LaTeX.Packages.Color {- Syntax table @@ -73,6 +68,7 @@ | HaTeX | Math Text | Footnote Syntax+ | Paragraph Syntax -- Monoid constructors | Append Syntax Syntax | Empty@@ -99,6 +95,7 @@ printSyntax HaTeX = "\\HaTeX" printSyntax (Math t) = let d = "$" in d <> t <> d printSyntax (Footnote s) = let d = "\\f" in d <> printSyntax s <> d+printSyntax (Paragraph s) = printSyntax s <> "\n\n" printSyntax (Append s1 s2) = printSyntax s1 <> printSyntax s2 printSyntax Empty = mempty @@ -120,7 +117,7 @@ xs <- many1 (char '#') let n = L.length xs s <- p_SyntaxWith PSection- ys <- string $ L.replicate n '#'+ _ <- string $ L.replicate n '#' return $ Section n s --------------------------------------- parseItem PBold = p_Chars Bold PBold '*' '*'@@ -135,7 +132,7 @@ itemTo pi b = modifyState $ \f -> \x -> if x == pi then b else f x p_SyntaxWith :: ParseItem -> Parser Syntax-p_SyntaxWith pi = between (pi `itemTo` False) (pi `itemTo` True) p_Syntax+p_SyntaxWith pi = between (pi `itemTo` False) (pi `itemTo` True) $ fmap mconcat $ many1 p_Unit p_Chars :: (Syntax -> a) -> ParseItem -> Char -> Char -> Parser a p_Chars f pi c1 c2 = fmap f $ between (char c1) (char c2) $ p_SyntaxWith pi@@ -143,17 +140,22 @@ p_Backslash :: Parser Syntax p_Backslash = do char '\\'- let ps = [ p_Code , p_LaTeX , p_HaTeX , fmap (Raw . fromString . (\c -> ['\\',c])) $ noneOf "f" ]+ let ps = [ p_InlineCode , p_LaTeX , p_HaTeX , fmap (Raw . fromString . (\c -> ['\\',c])) $ noneOf "f" ] f <- getState choice $ if f PFootnote then parseItem PFootnote : ps else ps -p_Code :: Parser Syntax-p_Code = do- d <- char '{' <|> char '['- let b = d == '{'- xs <- manyTill anyChar $ try $ string ['\\',if b then '}' else ']']- return $ Code b $ fromString xs+p_InlineCode :: Parser Syntax+p_InlineCode = do+ char '{'+ xs <- manyTill anyChar $ try $ string "\\}"+ return $ Code True $ fromString xs +p_BlockCode :: Parser Syntax+p_BlockCode = do+ string "\\["+ xs <- manyTill anyChar $ try $ string "\\]"+ return $ Code False $ fromString xs+ p_LaTeX :: Parser Syntax p_LaTeX = string "latex" >> return LaTeX @@ -182,17 +184,40 @@ return $ Math $ fromString xs p_Raw :: Parser Syntax-p_Raw = fmap (Raw . fromString) $ many1 $ noneOf resChars+p_Raw = fmap (Raw . fromString) $ many1 $ noneOf $ '\n' : resChars +p_Paragraph :: Parser Syntax+p_Paragraph = do+ x <- p_Unit+ xs <- manyTill p_Unit (try (void $ string "\n\n") <|> eof)+ return $ Paragraph $ mconcat $ x : xs++p_LineBreak :: Parser Syntax+p_LineBreak = do+ _ <- char '\n'+ return $ Raw "\n"+ resChars :: [Char] resChars = "$/\\#<>|*" -p_Syntax :: Parser Syntax-p_Syntax = do+p_Unit :: Parser Syntax+p_Unit = do f <- getState let xs = L.filter f allParseItems- ts = [ p_URL , p_IMG , p_Math , p_Raw , try p_Backslash ]- fmap mconcat $ many $ choice $ ts `mappend` fmap parseItem xs+ ts = [ p_LineBreak, p_URL , p_Math , try p_Backslash , p_Raw ]+ choice $ ts <> fmap parseItem xs++p_TopLevel :: Parser Syntax+p_TopLevel = choice+ [ p_LineBreak+ , parseItem PSection+ , p_IMG+ , try p_BlockCode+ , p_Paragraph+ ]++p_Syntax :: Parser Syntax+p_Syntax = fmap mconcat $ many $ p_TopLevel parseSyntax :: FilePath -> Text -> Either ParseError Syntax parseSyntax = runParser (withEOF p_Syntax) (const True)
hatex-guide.cabal view
@@ -1,5 +1,5 @@ Name: hatex-guide-Version: 1.1.0.0+Version: 1.2.0.0 Author: Daniel Díaz Build-type: Custom Category: LaTeX@@ -13,6 +13,8 @@ This library can be used to output the guide in different formats. A compiled pdf version of the latex output can be found at <http://daniel-diaz.github.com/projects/hatex/hatex-guide.pdf>.+ The online HTML version is in+ <http://daniel-diaz.github.com/projects/hatex/hatex-guide.html>. See the README file (<https://github.com/Daniel-Diaz/hatex-guide/blob/master/README.md>) for more details. Cabal-version: >= 1.6@@ -20,12 +22,7 @@ -- README file README.md -- Source of the guide- src/basics.htxg- src/class.htxg- src/epilogue.htxg- src/monad.htxg- src/packages.htxg- src/preface.htxg+ src/*.htxg -- Other resources (like images) res/machine.png @@ -40,6 +37,9 @@ , filepath , parsec >= 3.1.2 && < 3.2 , directory+ , blaze-html+ , transformers+ , time Exposed-modules: Text.LaTeX.Guide Other-modules:@@ -49,3 +49,5 @@ Text.LaTeX.Guide.Update Text.LaTeX.Guide.Backend.LaTeX Text.LaTeX.Guide.Backend.Wiki+ Text.LaTeX.Guide.Backend.HTML+ GHC-options: -Wall
src/basics.htxg view
@@ -15,18 +15,22 @@ As an example, you may take the /real numbers/ as objects and the ordinary multiplication as operation. Now that you know the math basics behind the \{Monoid\} class, let's see its definition:+ \[ class Monoid m where mempty :: m mappend :: m -> m -> m mconcat :: [m] -> m \]+ See that \{mappend\} corresponds to the monoid operation and \{mempty\} to its neutral element. The names of the methods may seem insuitable, but they correspond to an example of monoid: the lists with the appending \{(++)\} operation. Who is the neutral element here? The empty list:+ \[ xs ++ [] = [] ++ xs = xs \]+ This class plays a significant role in \hatex. Keep reading. ##LaTeX blocks##@@ -63,14 +67,18 @@ a number. How we deal with this? As you expect, with functions. We can create blocks that depend on values with functions that take these values as arguments, where these arguments can be blocks as well. For instance, we have the function \{linespread\} with type:+ \[ linespread :: Float -> LaTeX \]+ As you may know, a title in \latex can contain itself \latex code. So the type for the Haskell function \{title\} is:+ \[ title :: LaTeX -> LaTeX \]+ And this is, essentialy, the way to work with \hatex: *to create blocks and combine them*. Once you have your final block ready, you will be able to create its corresponding \latex code (we will see how later). Note that for every block there is a \latex code, but not for every code@@ -82,10 +90,12 @@ Inserting text in a \latex document is a constant task. You can create a block with text given an arbitrary \{String\} with the \{fromString\} function, method of the \{IsString\} class:+ \[ class IsString a where fromString :: String -> a \]+ Since there is a set of characters reserved to create commands or another constructions, \hatex takes care and avoids them replacing each reserved character with a command which output looks like the original character. For example, the backslash \{\\} is replaced with@@ -122,6 +132,7 @@ \f, is the block with \{a\} and \{b\} juxtaposed. For long lists of blocks, you can try it with \{mconcat\} as follows:+ \[ mconcat [ "I can see a " , textbf "rainbow" , " in the blue " , textit "sky" , "." ]@@ -134,6 +145,7 @@ the form of its correspondent \latex code. Say we have the next definition:+ \[ short = documentclass [] article@@ -141,8 +153,10 @@ <> author "John Short" <> document (maketitle <> "This is all.") \]+ Then, after calling \{renderFile "short.tex" short\}, the following file appears in the current working directory (line breaks added for easier visualization):+ \[ \documentclass{article} \title{A short message}@@ -152,18 +166,23 @@ This is all \end{document} \]+ Finally, you may use commands like \{latex\} or \{pdflatex\} to compile the \latex output to dvi or pdf. The function \{renderFile\} is not only for \{LaTeX\} values. Let's see its type:+ \[ renderFile :: Render a => FilePath -> a -> IO () \]+ The \{Render\} class that appears in the context is defined:+ \[ class Render a where render :: a -> Text \]+ So, it is the class of types that can be rendered to a \{Text\} value. The type \{LaTeX\} is an instance, but other types, like \{Int\} or \{Float\}, so are too. These instances are useful for creating blocks from other values. With the function
src/monad.htxg view
@@ -4,52 +4,67 @@ Fixed a monoid \{M\}, the \{M\}-writer monad is just all possible pairs of elements from \{M\} and elements from other types. Thus, the Haskell declaration is as follows\f Some authors write it using tuples, like this: \{data W m a = W (a,m)\}.\f:+ \[ data W m a = W m a \]+ Note that to get the monad we need to fix the type \{m\} (kind of monads is \{* -> *\}). To inject an arbitrary value into the monad (the Haskell \{return\} function) we use the neutral element (\{mempty\}) of the monoid.+ \[ inject :: Monoid m => a -> W m a inject a = W mempty a \]+ Think that no other element of \{m\} is possible to think: it is the only element we know of it! Like any other monad, \{W m\} is also a \{Functor\}. We just apply the function to the value.+ \[ instance Functor (W m) where fmap f (W m a) = W m (f a) \]+ Every \{Monad\} instance can be given by the two monad operations \{inject\} and \{join\}. We already defined the \{inject\} function. The other one deletes one monad type constructor.+ \[ join :: Monoid m => W m (W m a) -> W m a join (W m (W m' a)) = W (mappend m m') a \]+ In this function we use the other \{Monoid\} method to combine both values. It is important to note that in both monad operations \{inject\} and \{join\} we used \{mempty\} and \{mappend\} respectively. In practice, this is because they act equal. Indeed, they are equal if we forget the \{a\} value. Now, we are ready to define the \{Monad\} instance:+ \[ instance Monoid m => Monad (W m) where return = inject w >>= f = join (fmap f w) \]+ There is nothing to say about this instance. It is and standard definition valid to any monad. What we have done here is to hide in a monad a monoid with all its operations. We have created a machine that operates monoid values. To insert a value into the machine we need the \{tell\} function:+ \[ tell :: m -> W m () tell m = W m () \]+ When we execute the machine, it returns to us the result of operate all the values we have put on it.+ \[ execute :: W m a -> m execute (W m a) = m \]+ Let's see the machine working. For example, the \{Int\} type with addition forms a \{Monoid\}.+ \[ instance Monoid Int where mempty = 0@@ -62,21 +77,27 @@ tell 3 tell 4 \]+ When we evaluate \{example\} we get \{10\}, as expected. Using \{mapM_\} we can rewrite \{example\}.+ \[ example :: Int example = execute $ mapM_ tell [ 1 .. 4 ] \]+ |machine.png| ##The LaTeX Monad## Let's go back to the \{LaTeX\} type. Since \{LaTeX\} is an instance of \{Monoid\} we can construct its correspondent \{Writer\} monad.+ \[ type LaTeXW = W LaTeX \]+ The \{W\} machine is waiting now for \{LaTeX\} values.+ \[ example :: LaTeX example = execute $ do@@ -84,15 +105,19 @@ tell $ author "Monads lover" tell $ title "LaTeX and the Writer Monad" \]+ We put all that blocks in the machine, and it returns the concatenated block. We saved a lot of \{mappend\}'s, but we now have a lot of \{tell\}'s. No problem. Just redefine each function of blocks with \{tell\} and \{execute\}.+ \[ author' :: LaTeXW a -> LaTeXW () author' = tell . author . execute \]+ If it is done in a similar way with \{documentclass\} and \{title\}, every \{tell\} in \{example\} disappears.+ \[ example :: LaTeX example = execute $ do@@ -100,6 +125,7 @@ author' "Monads lover" title' "LaTeX and the Writer Monad" \]+ And we can now use the \{LaTeX\} machine more comfortably. However, we have all functions duplicated. This is why the \{LaTeXC\} class exists. We are going to talk about it later. @@ -109,21 +135,26 @@ named \{LaTeXT\}. The way to use it is the same, there are just a few changes. The first change is in type signatures. We need to carry an inner monad in every type.+ \[ foo :: Monad m => LaTeXT m a \]+ However, in practice, we can avoid it. Say we going to use an specific monad \{M\}.+ \[ type LaTeXW = LaTeXT M foo :: LaTeXW a \]+ Now, type signatures remain unchanged. The other change is a new feature: the \{lift\} function. With it we can do any computation of our inner monad at any time. For example, suppose we want to output some code we have in the file /foo.hs/. Instead of copy all its content, or read and carry it as an argument along the code, you can simply read that file using \{lift\} wherever you want.+ \[ type LaTeXIO = LaTeXT IO @@ -136,8 +167,10 @@ readCode "foo.hs" "It was a funny exercise." \]+ Different monads will give different features. In the case we are not interested in any of these features, it is enough to use the Identity monad.+ \[ type LaTeXW = LaTeXT Identity \]
src/packages.htxg view
@@ -10,6 +10,7 @@ This package is of vital importance if you use non-ASCII characters in your document. For example, if my name is /Ángela/, the /Á/ character will not appear correctly in the output. To solve this problem, use the \{Inputenc\} module.+ \[ import Text.LaTeX.Base import Text.LaTeX.Packages.Inputenc@@ -21,6 +22,7 @@ <> author "Ángela" <> title "Issues with non-ASCII characters" \]+ Don't forget to set to UTF-8 encoding your Haskell source too. ##Graphicx##@@ -28,8 +30,10 @@ With the \{Graphicx\} package you can insert images in your document and do some other transformations. In order to insert an image use the \{includegraphics\} function.+ \[ includegraphics :: LaTeXC l => [IGOption] -> FilePath -> l \]+ The list of \{IGOption\}'s allows you to set some properties of the image, like width, height, scaling or rotation. See the API documentation for details.