Execute a Markov algorithm: Difference between revisions

Added Haskell.
m (→‎{{header|C++}}: added a note)
(Added Haskell.)
Line 155:
}
</lang>
 
=={{header|Haskell}}==
<!-- This is essentially correct, but it could use some prettifying and a better interface. I'll make these changes sometime in the next few days (if nobody beats me to it). ~~~~ -->
 
<lang haskell>import Data.List (isPrefixOf)
import Data.Maybe (catMaybes)
import Control.Monad
import Text.ParserCombinators.Parsec
 
data Rule = Rule
{from :: String, terminating :: Bool, to :: String} deriving Show
 
main = case parse algorithm "foo" $ unlines l2 of
Right rs -> putStrLn $ run rs $ "I bought a B of As W my Bgage from T S."
Left e -> print e
where l =
["# This rules file is extracted from Wikipedia:",
"# http://en.wikipedia.org/wiki/Markov_Algorithm",
"A -> apple",
"B -> bag",
"S -> shop",
"T -> the",
"the shop -> my brother",
"a never used -> .terminating rule"]
l2 =
["# BNF Syntax testing rules",
"A -> apple",
"WWWW -> with",
"Bgage -> ->.*",
"B -> bag",
"->.* -> money",
"W -> WW",
"S -> .shop",
"T -> the",
"the shop -> my brother",
"a never used -> .terminating rule"]
 
algorithm :: Parser [Rule]
algorithm = liftM catMaybes $
(comment' <|> rule') `sepEndBy` (many1 newline)
where comment' = comment >> return Nothing
rule' = (liftM Just rule) <?> "rule"
 
comment = char '#' >> skipMany nonnl
 
rule :: Parser Rule
rule = liftM3 Rule
(manyTill nonnl $ try $ ws >> string "->" >> ws)
(option False $ char '.' >> return True)
(many nonnl)
 
 
nonnl = noneOf "\n"
ws = many1 $ oneOf " \t"
 
 
run :: [Rule] -> String -> String
run rules s = f rules s
where f [] s = s
f ((Rule from terminating to) : rs) s = g "" s
where g _ "" = f rs s
g before ahead@(a : as) = if from `isPrefixOf` ahead
then let new = (reverse before) ++ to ++ drop (length from) ahead
in if terminating then new else f rules new
else g (a : before) as</lang>
 
=={{header|J}}==
845

edits