I would like to know, how am i able to split a word with HXT ?
For example :
I have that ->
{-# LANGUAGE Arrows, NoMonomorphismRestriction #-}
import Text.XML.HXT.Core
import System.Environment --para uso do getArgs
data Class = Class { name ::String }
deriving (Show,Eq)
main = do
[src]<- getArgs
teams <- runX(readDocument [ withValidate no] src >>> getClass)
print teams
atTag tag = deep (isElem >>> hasName tag)
getClass = atTag "owl:Class" >>>
proc l -> do
className <- getAttrValue "rdf:about" -< l
returnA -< Class { name = className }
And i want to split the word ClassName !
Because the result of that programs (teams), gives me a set of hyperlink website (http:// ......) ! (Due to the XML file )
Can anyone give me some hints to solve it, please ?
Thank you !
You can use the function splitOn of the package split:
{-# LANGUAGE Arrows, NoMonomorphismRestriction #-}
import Text.XML.HXT.Core
import Data.List.Split (splitOn)
...
getClass = atTag "owl:Class" >>>
proc l -> do
className <- getAttrValue "rdf:about" -< l
returnA -< Class { name = splitOn "#" className !! 1 }
Example in ghci:
> import Data.List.Split
> let className = "http://www.xfront.com/owl/ontologies/camera/#Window"
> splitOn "#" className !! 1
Loading package split-0.2.2 ... linking ... done.
"Window"
The above code just works, if there is just one "#" in all of your URLs. If they are more complex, you shall have a look an the package Parsec.
Related
Starting with "A Simple Example" from the Pandoc documentation, I want to add citation processing functionality. The docs for Text.Pandoc.Citeproc show a function processCitations which supposedly processes citations. Yet given simple org-mode input, and a citation [#test2022], it doesn't seem to work. It compiles and runs just fine, but the output of the code below is: <p><span class="spurious-link" target="url"><em>testing</em></span> [#test2022]</p>, i.e., the citation isn't actually processed. What am I doing wrong? And how can I get this to process my citation?
import Text.Pandoc
import qualified Data.Text as T
import qualified Data.Text.IO as TIO
import Text.Pandoc.Filter
import Text.Pandoc.Citeproc
main :: IO ()
main = do
result <- runIO $ do
doc <- readOrg def (T.pack "#+bibliography: test.bib\n [[url][testing]]\n[#test2022]")
processed <- processCitations doc
writeHtml5String def processed
html <- handleError result
TIO.putStrLn html
For reference, here's my test.bib bibtex file:
#Book{test2022,
author = {Barus, Foobius},
title = {The Very Persistent Foo or Bar},
publisher = {Foobar Publications, Inc},
year = {2022}
}
I figured this out myself, eventually. Turns out you have to set some extensions, and some options, and set the metadata for the document:
{-# LANGUAGE OverloadedStrings #-}
import Text.Pandoc
import qualified Data.Text as T
import qualified Data.Text.IO as TIO
import Text.Pandoc.Filter
import Text.Pandoc.Citeproc
import qualified Data.Map as M
import Text.Pandoc.Builder (setMeta)
main :: IO ()
main = do
let exts = extensionsFromList [ Ext_citations ]
let readerOptions = def{ readerExtensions = exts}
let writerOptions = def{ writerExtensions = exts}
result <- runIO $ do
doc <- readMarkdown readerOptions (T.pack "Testing testing\n[#test2022]\n")
let doc' = setMeta (T.pack "bibliography") (T.pack "test.bib") doc :: Pandoc
processed <- processCitations doc'
writeHtml5String writerOptions processed
html <- handleError result
TIO.putStrLn html
I am trying to create tables directly using the Pandoc AST. I am trying a couple of approaches. However, nothing seems to be working. Rather than getting a table output, I just get [TABLE]. I have tried both the Pandoc builder monad, as well as directly creating a Table using the primitive constructors. I am not sure what I am getting wrong here.
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Main where
import Lib
import Data.Text (Text)
import qualified Data.Text as T
----------------------------------------
-- Pandoc imports
import Text.Pandoc
import Text.Pandoc.Builder
import Text.Pandoc.Options
import Text.Pandoc.Writers.Markdown
testTable :: IO ()
testTable = do
let my_tab = simpleTable [plain "Column 1"] [[plain "hello there"], [plain "hello there 2"], [plain "hello there 2"]]
let tab2 = Table [] [AlignDefault] [0.0] [[Plain [Str "Column",Space,Str "1"]]] [[[Plain [Str "Hello",Space,Str "there"]]] ,[[Plain [Str "Hello",Space,Str "there",Space,Str "2"]]] ,[[Plain [Str "Hello",Space,Str "there",Space,Str "3"]]]]
let other_tab = simpleTable colHeaders [testRow, testRow]
let thing = setTitle "Test report" $ doc $ para "Hey there" <> my_tab <> para "paragraph after table" <> singleton tab2 <> other_tab
md' <- runIO (writeMarkdown def thing)
case md' of
Left _ -> print "Damn"
Right md -> writeFile "my.md" (T.unpack md)
-- https://www.gwern.net/haskell/goodreadsToMarkdown.hs
colHeaders :: [Blocks]
colHeaders = map singleton [ Plain [Str "Title"]
, Plain [Str "Author"]
]
testRow = map singleton [ Plain [Str "Col 1"]
, Plain [Str "Col 2"]
]
main :: IO ()
main = do
print "hello"
testTable
let headers = map (plain . text) ["foo", "bar"]
let rows = map (map (plain . text)) [["1", "2"], ["3", "4"]]
-- md' <- runIO (writeMarkdown def (doc (simpleTable headers rows)))
let caption' = text "Hello"
md' <- runIO (writeMarkdown def (doc (table caption' [(AlignLeft, 1.0), (AlignLeft, 1.0)] headers rows)))
case md' of
Left _ -> print "Damn"
Right md -> print md
Markdown, by default, does not support tables. Pandoc implements multiple ways to output tables, but this has to be enabled. The easiest way is to use the set of extensions that make up pandoc flavored Markdown.
Instead of writeMarkdown def thing, you can write
writeMarkdown (def{writerExtensions = pandocExtensions}) thing
Now your program produces tables using one of pandoc's table extensions.
I wonder how to generate a bunch of constants based on a list of names.
I started with this working example:
ConstantCreation.hs
module ConstantCreation where
import Language.Haskell.TH
createConstant :: String -> Q [Dec]
createConstant constantName = do constantType <- newName constantName
constant <- newName constantName
return [ DataD []
constantType []
[NormalC constant []]
[] ]
MyConstants.hs
{-# LANGUAGE TemplateHaskell #-}
module MyConstants where
import ConstantCreation
$(do constantsDeclarations <- mapM createConstant
[ "MyFirstCustomConstant" ,
"MySecondCustomConstant" ]
return $ mconcat constantsDeclarations)
But things get tricky when I try to add a deriving Show.
I first tried changing the function createConstant like this:
createConstant constantName = do constantType <- newName constantName
constant <- newName constantName
return [ DataD []
constantType []
[NormalC constant []]
[GHC.Show.Show] ]
as suggested if I run the command runQ [d|data MyConstant = MyConstant deriving Show|] in GHCi, but it throws the error Not in scope: data constructor ‘GHC.Show.Show’
So I tried do define my function like this :
createConstant constantName = [d|data $(ConT $ newName constantName) = $(NormalC (newName constantName) []) deriving Show|]
but then I had the following error:
Cannot parse data constructor in a data/newtype declaration: $(NormalC
(newName constantName) [])
It would really be a pitty to have to define Show instances by hand, so I wonder what's going badly.
Thanks for any advice or explanation.
You can use ''Show to get the Type with the name that is in scope.
{-# LANGUAGE TemplateHaskell #-}
module Constant where
import Language.Haskell.TH
createConstant constantName = do
tname <- newName constantName
cname <- newName constantName
return [DataD [] tname [] [NormalC cname []] [''Show]]
Is there a way to test a node (Attribute Value) and use it with my if-condition ?
For example:
import Text.XML.HXT.Core
import System.Environment --para uso do getArgs
import Data.List.Split (splitOn)
data Class = Class { name ::String }
deriving (Show,Eq)
main = do
[src]<- getArgs
teams <- runX(readDocument [ withValidate no] src >>> getClass)
print teams
--Test
test = if (True) then getAttrValue "rdf:about" else getAttrValue "rdf:ID"
atTag tag = deep (isElem >>> hasName tag)
getClass = atTag "owl:Class" >>>
proc l -> do
className <- test -< l
returnA -< Class { name = splitOn "#" className !! 1}
On that example, i would like to test an attribute value and if it exists it return my then-condition otherwise the else-condition !
I saw the API of XMLArrow and it exists some function which will be able to do it (for example, isAttrib or hasAttrib) But it doesn't return a boolean ...
So ... I thought on other ways for solving it, but i think there must be a simpler solution to solve that...
Can someone gives me a hint please ?
You can use the functions of the module Control.Arrow.ArrowIf of the hxt package. Here you find the function ifA, a lifted version of the if-else-statement. For example the code
if (True) then getAttrValue "rdf:about" else getAttrValue "rdf:ID"
should be written as
ifA (constA True) (getAttrValue "rdf:about") (getAttrValue "rdf:ID")
Depending of what you want to archive, you should use derived functions of ifA like guards.
While I can use reify to get information about most other syntactic constructs, I couldn't find anything that would give some information about a module.
Unfortunately Template Haskell currently has no such capabilities. All the solutions involve parsing of the module's source-code. However the location and loc_filename functions of TH make it easy to locate the module with the calling splice.
Here is a solution extracted from the source code of one of my projects:
{-# LANGUAGE LambdaCase, TupleSections #-}
import Language.Haskell.TH
import qualified Data.Attoparsec.Text as AP
import qualified Data.Text.IO as Text
import qualified Data.Text as Text
import qualified Data.Char as Char
import Data.Maybe
import Data.List
import Control.Applicative
import Data.Traversable
import Prelude hiding (mapM)
reifyLocalFunctions :: Q [(Name, Type)]
reifyLocalFunctions =
listTopLevelFunctionLikeNames >>=
mapM (\name -> reifyFunction name >>= mapM (return . (name, ))) >>=
return . catMaybes
where
listTopLevelFunctionLikeNames = do
loc <- location
text <- runIO $ Text.readFile $ loc_filename loc
return $ map (mkName . Text.unpack) $ nub $ parse text
where
parse text =
either (error . ("Local function name parsing failure: " ++)) id $
AP.parseOnly parser text
where
parser =
AP.sepBy (optional topLevelFunctionP <* AP.skipWhile (not . AP.isEndOfLine))
AP.endOfLine >>=
return . catMaybes
where
topLevelFunctionP = do
head <- AP.satisfy Char.isLower
tail <- many (AP.satisfy (\c -> Char.isAlphaNum c || c `elem` ['_', '\'']))
return $ Text.pack $ head : tail
reifyFunction :: Name -> Q (Maybe Type)
reifyFunction name = do
tryToReify name >>= \case
Just (VarI _ t _ _) -> return $ Just $ t
_ -> return Nothing
tryToReify :: Name -> Q (Maybe Info)
tryToReify n = recover (return Nothing) (fmap Just $ reify n)