For some reason getLine is not working in my Jupiter notebook. Is there any way to create artificially an IO string so I can continue with some examples that need that?
I tried something like this:
main = do
foo :: IO String
foo << "sdf"
But didn't work obviously. Any way to do that? Thanks!
CodePudding user response:
A value of type IO String
represents an action that may do some IO
and produce a String
if it’s executed (ultimately, from main
). Normally, getLine
is such an action that reads a line of text from “standard input” (stdin
). If you just want to make your own action to use instead of getLine
, you can construct one quite simply using pure :: (Applicative f) => a -> f a
where f
is IO
and a
is String
in this case:
fakeGetLine :: IO String
fakeGetLine = pure "always the same string"
Aside: pure
is also called return :: (Monad m) => a -> m a
for historical reasons, but there’s no need to use it, since it’s the same function with a longer name and a slightly more restricted type.
Now, anywhere you would’ve entered getLine
, you can replace it with fakeGetLine
, or an expression such as pure "whatever string you wish to use"
. Likewise, if you needed a constant IO Int
, you could use pure 123
or pure (123 :: Int)
.
You can’t replace the standard getLine
, but it is possible to use your own definition with the same name of getLine
, provided that you hide the default one from scope using an import
…hiding
declaration:
import Prelude hiding (getLine)
getLine :: IO String
getLine = pure "always the same string"
Alternatively, you can in fact read from stdin
in an IPython notebook, as long as you open it with a frontend that supports the “input request” feature, such as JupyterLab or Deepnote. To the best of my knowledge, this is not currently supported in Hydrogen, nteract, or Spyder.
Finally, a method sometimes recommended for this issue in Python, which will not work in Haskell, is attempting to replace stdin
with a different handle. That technique is possible in Python because its stdin
is a mutable variable, while in Haskell, stdin
(like all variables) is immutable.