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.
Related
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.
Consider this variable
X = "1_2_3_4",
How to I get X into a binary string format?
So like this
<<"1_2_3_4">>
I'm getting all manner of errors trying to figure it out.
Thanks in advance,
Snelly.
Use the built in conversion function.
list_to_binary(X).
Thanks Dave! I had a quite a complex function concatinating variables
and strings/integers/atoms etc.
In case you are interested:
convert(L) ->
convert(L, <<>>).
convert([], Bin) ->
Bin;
convert([H|T], Bin) ->
convert(T, <<Bin/binary, H>>).
(what I was thinking of as Strings) as lists! Confusing
I think the reason that it's confusing is because sometimes the shell prints out a list as a string and sometimes it doesn't. In my opinion, things would be much clearer if the shell always output a list as a list unless you specifically requested a string.
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.
ive been lurking in this website for some time so ill finally post my 1st question.
atm i have to do a school project which is to create the game Sokoban with haskell,and so far its been going good until i got to the part where i have to validate the coordinates.
they come as such
11 2
3 4
5 6
it should return "Ok"
i have a function that turns them into a tuple of ints so i can check if they point to a place inside the map ,however that function doesnt give me a nice error message if its a a or just a number, which i need it to do that, for example
a a
11 2
3 4
the message should be "1", as in error in line 1.
1 3
2
4 5
the error message should be "2" too
Is there any way to do that sort of thing, ive ran out of ideas
the function that turns from String into (Int,Int)
processcoordinates::[String]->(Int,Int)
processcoordinates [x,y]= (read x,read y)
processcoordinates xs = error "invalid format"
Note:the function above is applied with the map function
among the things ive already tried but failed were using something along the lines of
valcoor::Int->[String]->Int
valcoor n []=-1
valcoor n ((x,y):t)
|isDigit x && isDigit y =valcoor (n+1) t
|otherwise =n
Note:sorry first time posting a question so im making a lot of mistakes :D
ive edited this function so many times so i cant remember exactly the kind of error messages it gave although among them were
Couldn't match expected type ‘[String]’
with actual type ‘([[Char]], [[Char]])’
which happened when testing with actual values such as
(["1","1"],["2","2"])
What you need is to create a parser that will convert a string input into a data structure.
As this is a homework, I don't want to give you a direct answer. Rather I'd suggest you to read Using Parsec from a great book Real World Haskell, which solves a problem very similar to yours. A parser will allow you to have nice and location-specific error messages.
Note that you probably want to treat the whole input as one String so that everything (including counting lines etc.) is done by the parser. So the signature you're looking would be probably something like
processcoordinates :: String -> Either ParseError [(Int, Int)]
where the left part of Either describes an error, and the right part a successful outcome.
I am trying to write a Forth interpreter in Haskell. There are many sub problems and categories to accomplish this, however, I am trying to accomplish the most basic of steps, and I have been at it for some time in different approaches. The simple input case I am trying to get to is "25 12 +" -> [37]. I am not worried about the lists in Forth are backwards from Haskell, but I do want to try and accommodate the extensibility of the input string down the road, so I am using Maybe, as if there is an error, I will just do Nothing.
I first tried to break the input string into a list of "words" using Prelude's words function. From there I used Prelude's reads function to turn it into a list of tuples (Int,String). So this works great, up until I get to a command "word", such as the char + in the sample problem.
So how do I parse/interpret the string's command to something I can use?
Do I create a new data structure that has all the Forth commands or special characters? (assuming this, how do I convert it from the string format to that data type?)
Need anything else, just ask. I appreciate the help thinking this through.
read is essentially a very simple string parser. Rather than adapting it, you might want to consider learning to use a parser combinator library such as Parsec.
There are a bunch of different tutorials about parser combinators so you'll probably need to do a bit of reading before they 'click.' However, the first example in this tutorial is quite closely related to your problem.
import Text.Parsec
import Text.Parsec.String
play :: String -> Either ParseError Integer
play s = parse pmain "parameter" s
pmain :: Parser Integer
pmain = do
x <- pnum `chainl1` pplus
eof
return x
pnum = read `fmap` many1 digit
pplus = char '+' >> return (+)
It's a simple parser that evaluates arbitrarily long lists:
*Main> play "1+2+3+4+5"
Right 15
It also produces useful parse errors:
*Main> play "1+2+3+4+5~"
Left "parameter" (line 1, column 10):
unexpected '~'
expecting digit, "+" or end of input
If you can understand this simple parser, you should be able to work out how to adapt it to your particular problem (referring to the list of generic combinators in the documentation for Text.Parsec.Combinator). It will take a little longer at first than using read, but using a proper parsing library will make it much easier to achieve the ultimate goal of parsing Forth's whole grammar.