Search
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.
print
show
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
getContents
t
solveTask t
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
maze.txt
$ runghc lab12.hs < maze.txt
Alternatively, we can compile it and then run the compiled executable file.
$ ghc lab12.hs $ ./lab12 < maze.txt