a function that turns [String] to (Int,Int) - haskell

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.

Related

Erlang - Converting String to Binary

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.

Haskell multiple actions within pattern match

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.

What is wrong in this Haskell function?

I decided to dive in functional programming world recently, and a friend told me about Haskell. I started my own researches on the language particularity and soon I got the main concepts. Then, I started working with lists and decided to rewrite some existent functions, just to practice.
I made my version of the reverse function, and called it revert. The function is defined as below:
revert :: [a] -> [a]
revert [] = []
revert a = revert (tail a) ++ [head a]
It works perfectly for me, as you can see in the image:
But then, I decided to make another test, receiving the result of the revert function on the same variable that I passed as a parameter, as you can see below:
It seems to execute the function normally, but when I check the value of x, it looks like it goes into a loop, and I need to interrupt the operation.
If I set the value on another variable, it works perfectly:
let y = revert x
Why does it happen? Is it some concept of functional programming that I am missing? Or some peculiarity with Haskell? I did some googling but was not able to get to an answer
PS: Sorry for the bad english
You're defining
x = revert x
So, substituting on the right, this gives
x = revert (revert x)
And so on. Another example would be
a = a + 1
To find out what a is, we need to evaluate the right hand side of the definition.
a = (a + 1) + 1
a = ((a+1)+1) + 1
And so on.
Bootom line: Haskell's = is very different from = in languages like C#, where it means assignment. In Haskell it means is defined as and this means we can substitute any occurance of an identifier with its definition without changing the meaning of the program. This is called referential transpareny.

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.

Convert one full String to ints and words as an interpreter in Haskell

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.

Resources