2

Now this is a thread that has been through Stack Overflow a lot. This also is covered by other sites but I still can't wrap my head around it fully. I've read different stuff from this site, I'm linking them in the bottom, but now to the question.

As usual, I'm trying to read lines from a file:

module BoardData where

readTable = do
  s <- readFile "projekt-board.txt"
  let content = lines s
  let removeEnd = init(content)
  let removeHead = tail(removeEnd)
  return removeHead

printTable [] = putStr ""
printTable [x] = putStrLn x
printTable (x:xs) = do
  let element = x
  putStrLn element
  printTable xs

I can't wrap my head around why I don't get a IO [String] -> [String] exception in the function readTable, however calling out printTable with an argument of readTable gives me an error.

  • Is there a way to hoax around the IO [String] type, maybe by accessing every element in the IO [String] list and then creating a new, pure one?
  • Or can I still do basic list operations with IO [String] type (however with this I have failed so far)?

Some reading material that I've gone through however it now has me even more confused:


[EDIT: An error thrown on call-out ]

*BoardData> let it = printTable readTable in it

<interactive>:1:21: error:
    • Couldn't match expected type ‘[String]’
                  with actual type ‘IO [String]’
    • In the first argument of ‘printTable’, namely ‘readTable’
      In the expression: printTable readTable
      In an equation for ‘it’: it = printTable readTable
Yun
  • 3,056
  • 6
  • 9
  • 28
Banana
  • 814
  • 1
  • 8
  • 28

1 Answers1

2

Just use your printTable inside the do-block to process the string that readTable produces:

readTable = do
  s <- readFile "projekt-board.txt"
  let content = lines s
  let removeEnd = init(content)
  let removeHead = tail(removeEnd)
  printTable removeHead

You can't get a pure value from the IO monad do-block out into the pure Haskell world; but you don't need to.

Each line in the IO do-block must have the same type, IO a -- a may vary of course, but it must be of the same form IO a. The type of the last line in do block is the type of the do block as a whole. For instance,

 #> :t putStr ""
putStr "" :: IO ()

So,

printTable            :: String -> IO ()
           removeHead :: String
printTable removeHead ::           IO ()

fits.

Will Ness
  • 70,110
  • 9
  • 98
  • 181
  • Add some remark about what happens when the input file has too few lines? – dfeuer Jan 03 '16 at 14:31
  • What i'd like to achieve would be manipulating the data i gather from the file, so the readTable function is just there to read the table into the list and printTable would be a function which would print the changes. Now let's say table contains elements [1,2,3] and i'd like to change it to [3,2,1] (and do other stuff with different functions later on) and then print it out (and not do it in readTable function). Is this type of manipulation possible? – Banana Jan 03 '16 at 14:32
  • @Banana so have a function `changeTable :: String -> String` and call it inside your `do` block too, like `...; let s2 = changeTable removeHead ; printTable s2`. – Will Ness Jan 03 '16 at 14:37
  • Okay, so all the action basically has to happen inside the readTable function as i understand? If i do any other I/O with user action, it has to be called out from there aswell? – Banana Jan 03 '16 at 14:40
  • inside a `do` block. You can have `readTable :: IO String`, then you use it inside another `do` block as `do { ... ; s <- readTable ; let s2 = trasnformTable s ; print s2 }`. – Will Ness Jan 03 '16 at 14:45
  • @dfeuer perhaps it's better to let the user ask another question about handling errors, to keep this focused on the basics?.. – Will Ness Jan 03 '16 at 14:46
  • @Banana and you write the `readTable` as `do { .... ; s <- ... ; return s }`, so it has type `IO String`, meaning, an `IO` computation producing a `String`. Then the `s` in `s <- readTable` will have type `String` (the pure type). – Will Ness Jan 03 '16 at 14:49
  • Okay, i'll try it out from here on. Thanks for explaining, marking you as an answer :) – Banana Jan 03 '16 at 14:52