Haskell multiple actions within pattern match - haskell

For a game I want to use animations, for that I want to pick a picture from a list, and then go to the next picture. However, for that I would need to do two things within one function which is not possible I think.
getPicture :: [IO Picture] -> Int -> IO Picture
getPicture a i | i < length a = (!!) i a && getPicture a (i+1)
| otherwise = (!!) i a && getPicture a (0)
Obviously I cannot use && to proceed to the next part, but I was wondering if there was a possibility to do this?

Seeing as you're always recursively calling getPicture, it looks to me like you just want all the pictures in order. You also have a base case which goes back to the first picture. Don't you think getPictures :: [IO Picture] -> IO [Picture] looks like a more suitable signature? It would just get all pictures in a sequence, no need to manually keep track of i.
Luckily there's sequence from Control.Monad which can do exactly this for you. We'll throw in a cycle which accommodates the "go back to the beginning" part.
do
pictures <- cycle <$> sequence getPictures
… -- animate the pictures as you wish
Of course I'm just guessing what you might actually want. For example, this will keep all the pictures (frames?) loaded in memory.

Related

Making a Map in Gloss

In PL class we were asked to make a pacman clone in Gloss, nevertheless I got stuck at making the map.
My approach was taking a .png of the classical pacman first level, and paste it in the render function so I don't need to draw everything by hand.
Nevertheless by doing so, the games lags horribly, I'm assuming that it's because the game renders the map in every step.
Is there some way to just render the map as a background a single time, or avoid the huge lag? Or am I taking a bad approach and it would it be better if I draw the components by hand using the Picture module?
I append the render function just in case I'm wiring it badly:
render :: PacmanGame -> IO Picture
render game = do
sprite <- fmap (head) (playerSprites $ player game)
let playerOne = uncurry translate (playerPos $ player game) $ sprite
map' <- pacmanMap
return $ pictures [map', playerOne]
Where pacmanMap :: IO Picture
It looks like you’re reloading the file in every call to render. You need to run the pacmanMap :: IO Picture action once, for example at startup in main; then you can just return the resulting static Picture from your render function. For example, you might store the reference to the current background image in the PacmanGame, or pass it as an additional argument to render.

Get elements of a list inside a list

When working with lists in Haskell, i can simply load my file into ghci and type head list or last list to get the information that I need. But if I have a list of lists, lets say: list = [[1,2,3],[4,5,6]], how can I get the first element (head) of the first list (in this case, 1), or the last element of the second list (in this case, 6), and so one?
If all you need is the first or last element, concat will flatten the list for you.
There is an indexing function (!!), so for your examples, head . (!!0) and last . (!!1) . If your question is more general, then please elaborate. Indexing is not great because it can throw errors if you attempt to index past the end of the list, so usually we try to work around that, eg. by saying "well I want to do the same thing to every element of the list so I don't really need the index" (map function) or "if I really do need the index then don't use it directly") (zip [0..], or use of eg. a record data type).
Also, Hoogle is your friend if you've not met it before. If you can break down your functions into simple ones you think might be standard, then search their type signatures, that's usually a good place to start. Hoogle [a] -> Int -> a even if you don't find exactly what you want, often if you find something similar and browse it's module or source code you can find something helpful.

How to handle runtime errors in Haskell?

I'm trying to learn Haskell by writing a simple console chess game. It displays a chess board and gets moves from standard input in SAN notation. Here's what I've got so far:
import System.IO
import Chess
import Chess.FEN
main = do
putStrLn "Welcome to Console Chess!"
putStrLn $ show defaultBoard
gameLoop defaultBoard
gameLoop board = do
putStr "Your move: "
hFlush stdout
move <- getLine
let newBoard = moveSAN move board
case newBoard of
Left _ -> do
putStrLn "Invalid move, try again..."
gameLoop board
Right b -> do
putStrLn $ show b
gameLoop b
The problem is that the call to the moveSAN function sometimes crashes the program, losing all progress made in the game. For instance, pressing Enter at the "Your move:" prompt produces:
Your move:
cchess: Prelude.head: empty list
Otherwise, entering a two-digit number produces:
Your move: 11
cchess: Error in array index
Entering two periods gives:
Your move: ..
cchess: Char.digitToInt: not a digit '.'
I would like to catch these errors and inform the user that the move they have entered is not in valid SAN notation. How can I do that?
In an ideal world, you would avoid functions like head and not have runtime errors at all. Runtime errors are fundamentally awkward, especially in Haskell.
In this case, you want to catch the runtime error. If you're content to turn it into a Maybe, you can use the spoon package.
Exceptions in Haskell are subtle thanks to laziness. Particularly, if you don't evaluate the part of the structure that has the exception, it won't fire. This is handled in spoon with two different functions:
spoon, which evaluates a structure deeply but requires an instance of a special typeclass
teaspoon which only evaluates your structure part of the way to weak head normal form
For your case, I think teaspoon should be fine. Try checking the result of the parse with:
teaspoon (moveSAN move board)
which should give you a Maybe value.
If that doesn't work, it means you need to evaluate more of the structure to hit the exception. It looks like Board does not implement the typeclass needed to deeply evaluate it with spoon, so your best bet is a bit hacky: use spoon on the result of show:
spoon (show $ moveSAN move board)
This will give you a Maybe String. If it's Just, the move parsed correctly; if it's Nothing, there was an error.
It's worth noting that the spoon package doesn't really do much: each function it has is only a couple of lines. At some point, it's worth figuring out how to handle exceptions in Haskell yourself, but for now spoon is just a bit more convenient and should work properly for you.

Turning a list into a set of coordinates [Haskell]

I am a starting out programmer and have my first few programming classes. We started off with functional programming, in this case using Haskell. I've managed to complete a few assignments already, but seem to have gotten stuck in one point and was hoping to get some help with it.
In order to not bore you with the entire code, my program right now is extracting a list of commands from a text file. I need to turn this list into a set of coordinates. What I mean is something along the lines of:
function :: [String] -> (Int, Int, Char)
where the function will receive, for example, the list ["0 0 N"] and output the coordinates and direction (0, 0, N).
I tried doing:
function [x y o] = (show x, show y, read o)
which would work if it were just Integers. I can't seem to get the Char part to work. I appologize if it's such a noobie question, but bear with me, please, I'm really new to all of this.
Thank you and best regards!
For your specific test case this should work:
function [(x:' ':y:' ':o:_)] = (read [x], read [y], o)
If your string contains spaces you need to match on them as well if you want to do it like that.
But that's probably not what you actually want. It would break for inputs like ["12 23 S"] or ["3 5 W", "2 8 E"].
If your input is actually a list of Strings like your signature says you should probably write two functions: One that deals with a single String and one that applies your other function to all Strings in the list. Look at the functions map and words and think about how you can use them to solve your problem.

Which Monad do I need?

This is something of an extension to this question:
Dispatching to correct function with command line arguments in Haskell
So, as it turns out, I don't have a good solution yet for dispatching "commands" from the command line to other functions. So, I'd like to extend the approach in the question above. It seems cumbersome to have to manually add functions to the table and apply the appropriate transformation function to each function so that it takes a list of the correct size instead of its normal arguments. Instead, I'd like to build a table where I'll add functions and "tag" them with the number of arguments it needs to take from the command line. The "add" procedure, should then take care of composing with the correct "takesXarguments" procedure and adding it to the table.
I'd like to be able to install "packages" of functions into the table, which makes me think I need to be able to keep track of the state of the table, since it will change when packages get installed. Is the Reader Monad or the State Monad what I'm looking for?
No monad necessary. Your tagging idea is on the right track, but that information is encoded probably in a different way than you expected.
I would start with a definition of a command:
type Command = [String] -> IO ()
Then you can make "command maker" functions:
mkCommand1 :: (String -> IO ()) -> Command
mkCommand2 :: (String -> String -> IO ()) -> Command
...
Which serves as the tag. If you don't like the proliferation of functions, you can also make a "command lambda":
arg :: (String -> Command) -> Command
arg f (x:xs) = f x xs
arg f [] = fail "Wrong number of arguments"
So that you can write commands like:
printHelloName :: Command
printHelloName = arg $ \first -> arg $ \last -> do
putStrLn $ "Hello, Mr(s). " ++ last
putStrLn $ "May I call you " ++ first ++ "?"
Of course mkCommand1 etc. can be easily written in terms of arg, for the best of both worlds.
As for packages, Command sufficiently encapsulates choices between multiple subcommands, but they don't compose. One option here is to change Command to:
type Command = [String] -> Maybe (IO ())
Which allows you to compose multiple Commands into a single one by taking the first action that does not return Nothing. Now your packages are just values of type Command as well. (In general with Haskell we are very interested in these compositions -- rather than packages and lists, think about how you can take two of some object to make a composite object)
To save you from the desire you have surely built up: (1) there is no reasonable way to detect the number of arguments a function takes*, and (2) there is no way to make a type depend on a number, so you won't be able to create a mkCommand which takes as its first argument an Int for the number of arguments.
Hope this helped.
In this case, it turns out that there is, but I recommend against it and think it is a bad habit -- when things get more abstract the technique breaks down. But I'm something of a purist; the more duct-tapey Haskellers might disagree with me.

Resources