Search code examples
haskellio

Haskell: IO [String] to [String]


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

Solution

  • 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.