Output Integer to stdout in Haskell

28,647

Solution 1

nth is a function, not an IO action:

main = do
  n <- getLine
  let result = nth (read n :: Integer)
  print result

Solution 2

The do syntax unwraps something within a monad. Everything on the right hand side of the arrow must live within the IO monad, otherwise the types don't check. An IO Integer would be fine in your program. do is syntactic sugar for the more explicit function which would be written as follows:

Recall that (>>=) :: m a -> (a -> m b) -> m b

main = getLine >>= (\x ->
       nth >>= (\y ->
       print y))

But nth is not a monadic value, so it doesn't make sense to apply the function (>>=), which requires something with the type IO a.

Share:
28,647
Iulius Curt
Author by

Iulius Curt

I try to learn everything. I'll let you know if I succeed. LinkedIn profile Github profile

Updated on December 29, 2020

Comments

  • Iulius Curt
    Iulius Curt over 3 years

    I have a simple function like:

    nth :: Integer -> Integer
    

    And I try to print it's result as follows:

    main = do
        n <- getLine
        result <- nth (read n :: Integer)
        print result
    

    The following error is generated:

    Couldn't match expected type `IO t0' with actual type `Integer'
    In the return type of a call of `nth'
    In a stmt of a 'do' expression:
        result <- nth (read n :: Integer)
    

    Also tried with putStrLn and a lot of other combinations with no luck.
    I can't figure it out and I would need some help, being that I don't fully understand how stuff works around these IOs.

  • Louis Wasserman
    Louis Wasserman about 12 years
    Because it doesn't do any I/O...?
  • Thomas M. DuBuisson
    Thomas M. DuBuisson about 12 years
    Do syntax and binds (x <- action) is only used for Monads. If you are a beginner then chances are the only monad you're using is IO. if your function isn't in the form func :: a -> IO b or even just func :: IO b, then you can't use bind but you can use a let statement.
  • Iulius Curt
    Iulius Curt about 12 years
    Great, thanks. But what's the difference between using a let before print and call directly print nth (read...)?
  • Iulius Curt
    Iulius Curt about 12 years
    Thanks, now I'm like "Oh, so from here came that expected m0 a0 I was receiving..."
  • nponeccop
    nponeccop about 12 years
    There is no difference. print (nth (read n :: Integer)) will work as well. <- is not to save intermediate values - it's to unwrap monadic values. Use let to save intermediate values (in do blocks let has slightly different syntax than outside of do blocks) and <- to extract values from monadic values.
  • nponeccop
    nponeccop about 12 years
    To clarify little more, m0 comes from the fact that (>>=) :: Monad m => m a -> (a -> m b) -> m b. It works for any monad, not only IO, and in your case compiler didn't have a chance to figure out that m is IO, so it put m0 in the error message.