Couldn't match expected type `IO ()' with actual type `a0 -> m0 a0' - haskell

Here's my code:
doSomething :: IO Bool -> IO () -> IO ()
doSomething cond body = cond >>= ( \condition -> if condition then return else body )
It gives me this error:
Couldn't match expected type `IO ()' with actual type `a0 -> m0 a0'
In the expression: return
In the expression: if condition then return else body
In the second argument of `(>>=)', namely
`(\ condition -> if condition then return else body)'
I also tried this equivalent notation:
whileM :: IO Bool -> IO () -> IO ()
whileM cond body = do
condition <- cond
if condition then return else body
but I am getting more or less the same notation. I understand that the error is saying that the function expects me to return a Monad but instead I am returning a function which transforms a0 into a monad m a0. How can I fix this?

Unlike in (pretty much all) other languages, in Haskell, return doesn't mean "terminate this code and go back to the next line of what called it".
In Haskell, it (roughly) means "wrap this thing up in a monad". In the context of the do notation, this often occurs at the place in the code where control is given back to the "caller" (again, this isn't really the correct word, but will do in this analogy).
Hence, return needs a parameter here (the thing to be wrapped up).... return is of type Monad m => a -> m a, but your function is returning type IO (). The thing you will therefore need to wrap up is of type (), a type with just one element, '()' itself.
Change return to return (), and see if that works.

Related

read::Int not working in Haskell in example

Here is the problem. It looks simple yet
main = do
s <- getContents
let list = map (read::Int) (words s)
print list
Couldn't match expected type `Int' with actual type `String -> a0'
Probable cause: `read' is applied to too few arguments
In the first argument of `map', namely `(read :: Int)'
In the expression: map (read :: Int) (words s)
The problem was that I thought :: is like casting and I have to put the return type. The solution was to add full wanted |function signature instread.
read is a function (of type Read a => String -> a), so it can't have type Int. You could do read :: String -> Int, or you could put a type signature on list rather than read, so you get:
let list :: [Int]
list = map read (words s)

Type inference with GADTs - a0 is untouchable

Lets say I have this program
{-# LANGUAGE GADTs #-}
data My a where
A :: Int -> My Int
B :: Char -> My Char
main :: IO ()
main = do
let x = undefined :: My a
case x of
A v -> print v
-- print x
compiles fine.
But when I comment in the print x, I get:
gadt.hs: line 13, column 12:
Couldn't match type ‘a0’ with ‘()’
‘a0’ is untouchable
inside the constraints (a1 ~ GHC.Types.Int)
bound by a pattern with constructor
Main.A :: GHC.Types.Int -> Main.My GHC.Types.Int,
in a case alternative
at /home/niklas/src/hs/gadt-binary.hs:13:5-7
Expected type: GHC.Types.IO a0
Actual type: GHC.Types.IO ()
In the expression: System.IO.print v
In a case alternative: Main.A v -> System.IO.print v
Why do I get this error in line 13 (A v -> print v) instead of only in the print x line?
I thought the first occurrence should determine the type.
Please enlighten me :)
Well, first note that this has nothing to do with the particular print x: you get the same error when ending main with e.g. putStrLn "done".
So the problem is indeed in the case block, namely in that only the last statement of a do is required to have the type of the do block's signature. The other statements merely have to be in the same monad, i.e. IO a0 rather than IO ().
Now, usually this a0 is inferred from the statement itself, so for instance you can write
do getLine
putStrLn "discarded input"
though getLine :: IO String rather than IO (). However, in your example the information print :: ... -> IO () comes from inside the case block, from a GADT match. And such GADT matches behave differently from other Haskell statements: basically, they don't let any type information escape its scope, because if the information came from the GADT constructor then it's not correct outside of the case.
In that particular example, it seems obvious enough that a0 ~ () has nothing at all to do with the a1 ~ Int from the GADT match, but in general, such a fact could only be proven if GHC traced for all type information where it came from. I don't know if that's even possible, it would certainly be more complicated than Haskell's Hindley-Milner system, which heavily relies on unifying type information, which essentially assumes that it doesn't matter where the information came from.
Therefore, GADT matches simply act as a rigid “type information diode”: the stuff inside can never be used to determine types on the outside, like that the case block as a whole should be IO ().
However, you can manually assert that, with the rather ugly
(case x of
A v -> print v
) :: IO ()
or by writing
() <- case x of
A v -> print v

How do I specify a type variable used in an inline type, is the same as a type variable used in a function definition?

(Apologies if my terminology is wrong).
I'm trying to write a wrapper function that handles exceptions: if the given IO action throws, it returns Nothing (inside an IO context of course), but if the given IO action succeeds, it returns Just v.
tryMaybe :: IO a -> IO (Maybe a)
tryMaybe action = do
result <- (try action) :: IO (Either SomeException a)
return $ case result of
Left _ -> Nothing
Right v -> Just v
This results in the compiler error message:
Couldn't match type `a' with `a1'
`a' is a rigid type variable bound by
the type signature for tryMaybe :: IO a -> IO (Maybe a)
at src/Database.hs:33:13
`a1' is a rigid type variable bound by
an expression type signature: IO (Either SomeException a1)
at src/Database.hs:35:15
Expected type: IO a1
Actual type: IO a
In the first argument of `try', namely `action'
I'm guessing that the type variable a in the first line isn't the same as the a in the third line - they just happen to have the same name in the source code, and the compiler has renamed it a1 in the error message.
So how do I tell Haskell that these are the same types?
You need to enable the ScopedTypeVariables extension, and the change the type signature of the top-level function to start with forall a .:
{-# LANGUAGE ScopedTypeVariables #-}
...
tryMaybe :: forall a . IO a -> IO (Maybe a)
...
The forall syntax brings the type variable a into scope for the entire body of tryMaybe, rather than it being limited to the type signature which is the default. This is mainly a historical anomaly rather than a deliberate design.

Couldn't match expected type `Int' with actual type `IO [Int]'

Can someone please explain what's going on in my function.
arrayReader :: [Int] -> IO [Int]
arrayReader arr = do
item <- readLn
return $ if item == 0
then arr
else arrayReader item:arr
But Haskell is not happy with the 6th line:
reader.hs:6:17:
Couldn't match expected type `Int' with actual type `IO [Int]'
In the return type of a call of `arrayReader'
In the first argument of `(:)', namely `arrayReader item'
In the expression: arrayReader item : arr
Can someone explain what needs to be changed to make this function compile?
Firstly, you have a precedence error - arrayReader item:arr parses as (arrayReader item):arr. You need to write arrayReader (item:arr).
Secondly, arrayReader produces something of type IO [Int], but in this context return takes something of type [Int] and produces IO [Int]. You need to rearrange your code so that return is only called on arr, not on the result of arrayReader.

Type signature "Maybe a" doesn't like "Just [Event]"

I'm still learning Haskell and need help with the type inference please!
Using packages SDL and Yampa
I get the following type signature from FRP.Yampa.reactimate:
(Bool -> IO (DTime, Maybe a))
and I want to use it for:
myInput :: Bool -> IO (DTime, Maybe [SDL.Event])
myInput isBlocking = do
event <- SDL.pollEvent
return (1, Just [event])
...
reactimate myInit myInput myOutput mySF
but it says
Couldn't match expected type `()'
against inferred type `[SDL.Event]'
Expected type: IO (DTime, Maybe ())
Inferred type: IO (DTime, Maybe [SDL.Event])
In the second argument of `reactimate', namely `input'
In the expression: reactimate initialize input output process
I thought Maybe a allows me to use anything, even a SDL.Event list?
Why is it expecting Maybe () when the type signature is actually Maybe a?
Why does it want an empty tuple, or a function taking no arguments, or what is () supposed to be?
The full type signature of reactimate is
IO a -- # myInit
-> (Bool -> IO (DTime, Maybe a)) -- # myInput
-> (Bool -> b -> IO Bool) -- # myOutput
-> SF a b -- # mySF
-> IO ()
The same a and b must match, that means if your myInput has type Bool -> IO (DTime, Maybe [SDL.Event]), then all other a must also be [SDL.Event]. Hence, to match the types, you need to ensure
myInit :: IO [SDL.Event] -- # **not** IO ().
mySF :: SF [SDL.Event] b
BTW, () is the unit type.

Resources