Coming soon. > pure W – Applicative approach
free :: Parser Block free = do char ' '
return F
row :: Parser [Block] row = do bs ← many (wall <|> free)
char '\n' return bs
– row = many (wall <|> free) <* char '\n' – Applicative approach
> parse row “ ### # \n# #\n” Just ([F,F,W,W,W,F,W,F],“# #\n”) </code>
A maze is just a (possibly empty) sequence of rows. The input starts with the start and goal definitions, followed by a maze.
mapP :: Parser Maze mapP = do rs <- many row return (M rs) -- mapP = M <$> many row -- Functor approach file :: Parser Task file = do p <- def "start" q <- def "goal" m <- mapP return (p,q,m) -- Applicative approach -- file = (,,) <$> def "start" -- <*> def "goal" -- <*> mapP
Finally, we put all the pieces together. We start with a function taking a task and returning an IO action that
either displays the found solution or informs that there is no solution. Note that the function print
is just the composition of show
followed by putStrLn
.
solveTask :: Task -> IO () solveTask t@(p,q,m) = case solve t of Nothing -> putStrLn "No solution exists." Just ps -> print $ drawSol m ps
We need to create a main
function returning the main IO action to be executed. It reads completely the input by getContents
.
Then it parses the input. If the parser fails or does not consume the whole input, it prints an error message.
Otherwise, we have a task t
and solveTask t
can be executed.
main :: IO () main = do str <- getContents case parse file str of Nothing -> putStrLn "Incorrect task!" Just (t, "") -> solveTask t Just (_, out) -> putStrLn $ "Unused input: " ++ out
Now, if we have a text file maze.txt
with the input, we can run our source code by
$ runghc lab12.hs < maze.txt
Alternatively, we can compile it and then run the compiled executable file.
$ ghc lab12.hs $ ./lab12 < maze.txt