'Couldn´t match expected type error in haskell

I´m trying to implement a function that saves the highest score of a player in a game through a txt file. This is the code:

import System.IO
import System.Directory

saveHighScore:: Int -> IO()
saveHighScore num = do
  let stringNum = "" ++ show num
  let file = "score.txt"
  writeFile file stringNum

readHighScore:: IO() -> Int
readHighScore = do 
  content <- openFile "score.txt" ReadMode
  score <- hGetContents content
  let highScore = read score :: Int
  return highScore

But the code is giving this error and I don´t know what to do:

localStorage.hs:17:9: error:
* Couldn't match expected type: IO () -> Int
              with actual type: IO Int
* In a stmt of a 'do' block:
    content <- openFile "score.txt" ReadMode
  In the expression:
    do content <- openFile "score.txt" ReadMode
       score <- hGetContents content
       let highScore = ...
       return highScore
  In an equation for `readHighScore':
      readHighScore
        = do content <- openFile "score.txt" ReadMode
             score <- hGetContents content
             let highScore = ...
             ....
 |
17|         content <- openFile "score.txt" ReadMode
 |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


Solution 1:[1]

The error message is telling you exactly what's wrong. You claim your function has type IO () -> Int, but it's impossible for any interesting function to have this type. The only possible implementation is a constant function that ignores the IO () and produces the same result regardless of its input.

The right type is the one the compiler is suggesting, IO Int.

Solution 2:[2]

In the other answer, amalloy gives the explanation.

To fix the issue, the easiest step is to remove the type declaration:

readHighScore = do 
  content <- openFile "score.txt" ReadMode
  score <- hGetContents content
  let highScore = read score :: Int
  return highScore

Then load the file in GHCi and query GHCi about the type:

> :t readHighScore
readHighScore :: IO Int

That's the type. You can add it back as a type declaration:

readHighScore :: IO Int
readHighScore = do 
  content <- openFile "score.txt" ReadMode
  score <- hGetContents content
  let highScore = read score :: Int
  return highScore

There are lots of tools and add-ons that can do this in your IDE of choice, but GHCi works everywhere, I should think.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Mark Seemann