You've written:
getBoard :: String
That doesn't say that getBoard
is a function or procedure that returns a String
. Rather, it says that getBoard
is a String
; I mean some specific String
like "Hello world"
or "foo"
, for example. Obviously, that's wrong. Rather, getBoard
is a procedure you can perform that produces a String
as its result. In Haskell, the way you say that is:
getBoard :: IO String
So that's the right answer. If that answer doesn't work for you, please provide more context so we can understand why.
When you say "Note: The getBoard function MUST return a String", that's almost exactly what getBoard :: IO String
means: getBoard
is a procedure that returns a String
. (One subtle point here is that I've said "procedure" instead of "function". That's because in Haskell, "function" means something different from what you're probably expecting from other languages. A function is something that takes parameters. Because getBoard
doesn't take parameters, it's not a function, but it is a procedure.)
Did you mean that you want it to be a String
, rather than return one? This doesn't make much sense, though. Which specific String
would you like it to be?
Okay, now is where I reluctantly admit that there is one way to tell Haskell (incorrectly) that getBoard
is a String
. You shouldn't do this unless you're a pretty advanced Haskell programmer, understand the implications, and have a good reason it's worth it. But you can import System.IO.Unsafe
and then wrap the definition of getBounds
with the unsafePerformIO
function. What this says is: "Pretend that getBounds
is some specific String
rather than a procedure. Any time you need to know which String
it is, go sneak off behind the scenes and run this procedure to find out."
Note that if you do this, there is NO guarantee about when your program will read the file, how many times your program will read the file, or even whether your program will read the file at all! All of these things can depend on things like strictness of evaluation, which optimization choices like inlining the compiler makes, and so on. If the contents of the file change while your program is running, the result is undefined. This is not a normal way to write Haskell, other Haskell programmers will give you weird looks and assume you're kind of clueless if you do it without a good reason, and you should probably just forget about it until you're more on the advanced side. I only mentioned it because I don't want to give an incomplete response.