Hello great programmers out there,
I'm doing my first steps in haskell and have a function that confuses me:
import Data.List.Split
getncheck_guesslist = do
line <- getLine
let tmp = splitOneOf ",;" line
map read tmp::[Int]
splitOneOf is in Data.List.Split (i installed it with cabal install split)
splitOneOf :: (Eq a)=> [a]->[a]->[[a]]
From the error I get it that there is some type incorrectness - but don't know how to solve this conflicts as IO is still a mystery to me
I want to read an input of integers separated by commas or semicolons and get a list of integers so:
thank you in advance for thoughts and hints - yours ε/2
When you're writing a function that uses the IO monad, any value you want to return from the function must also be in the IO monad.
This means that, instead of returning a value with type [Int]
, you have to return something with type IO [Int]
. To do this, you use the return
function, which "wraps up" the value into IO
(it actually works for any monad).
Just change the last line to wrap your value with return
, like this:
getncheck_guesslist = do
line <- getLine
let tmp = splitOneOf ",;" line
return (map read tmp :: [Int])
The "right way" to do it in Haskell is to separate IO from, well, everything else. The direct translation of your code would be this:
getncheck_guesslist :: IO [Int]
getncheck_guesslist = do line <- getLine -- get
return (check_guesslist line) -- check
check_guesslist :: String -> [Int]
check_guesslist line = let tmp = splitOneOf ",;" line
in map read tmp
Notice that getncheck_guesslist
is simply an IO action. The function doesn't have input parameters, even though it does require (IO) input from getLine
.
Also notice that getncheck_guesslist
is a simple modification of the getLine
IO action. Isn't there a combinator that would let me push a function to act on the value inside a monad? Stop. Hoogle time!
I have a function (a -> b)
. I have a value of the input type, but it's stuck in a monad m a
. I want to perform the function inside the monad, so the result will inevitably be stuck in the monad too m b
. Putting that all together, we hoogle (a -> b) -> m a -> m b
. Lo and behold, fmap
is just what we were looking for.
get_guesslist = check_guesslist `fmap` getLine
-- or, taking it a step further
get_guesslist = (map read . splitOneOf ",;") `fmap` getLine :: IO [Int]
As a final note, whenever you code a method with the name like somethingAndSomethingElse
, it's usually better coding style to write and invoke something
and somethingElse
as two separate methods. For the final versions, I just renamed it get_guesslist
, since conceptually that's what it does. It gets the guesses as a list of Ints.
As a final final note, I have left off at the point where barsoap started. ;) fmap
is the same as <$>
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With