-1

I want to write a file that has information about when I can schedule an exam, the date(given a limit of days for all the exams) and which room(given a limited number of rooms) but the exam subject is to be defined according to a file which has all the, number id of the subjects, the year of the subjects and the name of the subjects, all in separate lines, and there can't be more than one exam in the same room.

I would like store those 3 values for each subject in a list of tuple so when I print it out I just get a list of tuples. I'm trying to tackle this in Haskell and so far I got to this point but, I can't seem to understand the errors this code is giving me.

Sorry for the dumb question, kind of new to Haskell, also the variables and function names are not in English.

     atribuituple dias sala (li:lis) tupleList = do
                    if dias > 0 then
                         atribuituplesala dias sala last(words li) tupleList
                         atribuituple (dias-1) sala lis tupleList
                    else
                         return()
                    
      
     atribuituplesala dias sala uc tupleList = do
                    if  sala > 0 then
                         tupleList ++ (dias,sala,uc)
                         atribuituplesala dias (sala-1) uc tupleList
                    else
                         return()

     save_uc_dia dias sala = do
               ucs <- openFile "ucs.txt" ReadMode
               exames_uc_dia_sala_W <- openFile "exames_uc_dia_sala.txt" WriteMode
               let tupla = [] 
               atribuituple dias sala (lines ucs) tupla
               writeFile "exames_uc_dia_sala.txt" tupla
               hClose ucs
               hClose exames_uc_dia_sala_W

I was expecting to receive a list of tuples in a file called "exames_uc_dia_sala.txt" according to all the limitations the initial problem has given me.

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
  • Your `atribuituple` and `atribuituplesala` functions don't appear to actually do any IO so I'm not sure why they're using `do`. – Chris Jun 03 '23 at 18:09
  • curious as to why you would only use "do" when performing IO tasks? any specific reason @Chris – Francisco Marinho Carvalho Jun 03 '23 at 18:26
  • 3
    Because `do` is used to compose monadic actions and that's their main use. – cafce25 Jun 03 '23 at 19:34
  • 1
    Note: You're writing a very procedual style Haskell, that's not very idiomatic. Your functions all return `IO ()` or in other words nothing, to change something usually you'd return the modified value, and the `return` function probably does something different from what you're used to. Also it's hard to explain errors we don't see, please add the full error messages. – cafce25 Jun 03 '23 at 19:36
  • 1
    You want to break your problem down as much as you can. Forget the IO that gets the data into your program. How will you operate on that data? Does that work? Good, now you can worry about the IO. – Chris Jun 03 '23 at 19:42
  • @FranciscoMarinhoCarvalho: `do` is not just to define a block of code. `do` can only be used in a monadic context. – Willem Van Onsem Jun 03 '23 at 20:21
  • Immediate problem: `ucs` is an `Handle`, not a `String`. You need to *read* from the handle first before you can apply `lines` to split the single string into a list of strings. – chepner Jun 05 '23 at 14:56

1 Answers1

1

Imagine you're writing a Haskell program to create a list of integers counting from some starting integer n down to 1. If you wrote it in a style similar to your atribuituplesala function, it would look something like this:

countdown n lst = do
  if n > 0 then
    lst ++ [n]
    countdown (n-1) lst
  else
    return ()

But there's a pretty big problem with this solution: as Haskell code, it doesn't make any sense! Nothing about it is correct.

The expression lst ++ [n] doesn't append n to lst. Placing two expressions on separate lines after the "then" keyword:

 lst ++ [n]
 countdown (n-1) lst

does not "run" these expressions sequentially. The final statement return () does not "stop processing" and return the final list.

Most of your assumptions about how Haskell works are wrong, and none of this code will work as you intend.

(If it helps to understand where I'm coming from, and assuming you know a little Python, imagine a friend comes to you with their Python code to add up the numbers from 1 to 100, and presents you with something like this:

x = 1
result = 0
if x < 100:
    x + 1
    sum(result,x)
    pass
else:
    return result

Even though you can sort of understand their thought process from this code, there's really no way to help them fix it, except by rewriting it for them from scratch. It's pretty obvious your friend hasn't learned even the absolute basics of Python -- how variable assignments, loops, and functions work -- and they absolutely must start working through some beginner tutorials and learning materials before tackling even a simple problem like this.)

So, in that spirit, I don't think you've yet learned the absolute basics of Haskell. You should work through some tutorials and learning materials before tackling a problem like this.

The answers to this SO question provide some pointers to good resources.

K. A. Buhr
  • 45,621
  • 3
  • 45
  • 71