I start learning Haskell, and just tried a simple code, and it shows me some errors when I run
doubleMe :: Int -> Int
doubleMe x = x + x
main = do
doubleMe 2
ghc -c first.hs
The errors are:
$ ghc -c first.hs
first.hs:4:1:
Couldn't match expected type IO t0' with actual typeInt'
In the expression: main
When checking the type of the function `main'
While I use GCHi to debug, there were no issues to load doubleMe function first, and call it later. Any help would be appreciated.
Every function in Haskell returns a value of a certain type.
In this case, the doubleMe function returns a value of the Int type. When you load a file from the ghci interpreter, it loads all the functions from the file and makes them available to you.
The main function is a slightly special function, much like in other languages. It defines the entry point of a Haskell program. However, since it is just another Haskell function it too must return a value of a particular type. The main function is constrained to return a value of the IO type, most commonly IO ().
IO itself is quite special too, belonging to a class of types called monads. You can read up on the IO monad here.
Let us now return to your code:
main = do
doubleMe 2
Ignore the do syntax for a moment. You're basically telling the compiler that the main function returns doubleMe 2 which is of type Int. This won't fly. main has to return a value of IO type. In which case, you can use the return function to convert an Int value into an IO Int value. (return functions are functions that all monadic types must have. Very simply put, it converts a value of any type, into a monadic value.)
So this becomes:
main = do
return (doubleMe 2)
This is perfectly valid code, and will compile. However, once you run the program, you'll notice that it doesn't do anything. That's because the program returns the value 4.
In fact, you can write it without the do, and it becomes:
main = return (doubleMe 2)
This will work too.
Let us assume however, that you want to print out the value. This is where IO really comes in. Printing to a screen is an IO action.
main = do
print (doubleMe 2)
return (doubleMe 2)
A do expression allows you to chain a set of IO actions. So your program will still return the value 4 but it will first evaluate the expression print (doubleMe 2). As expected, that actually results in printing the value doubleMe 2.
Examine the print function in ghci.
> :t print
print :: Show a => a -> IO ()
The print function works on a value of any type that can be shown and it results in an IO action (printing to the screen) but returns nothing ().
All of these examples work, and will hopefully make things a little clear. (Look at the type signatures for main).
-- main :: IO Int
main = return (doubleMe 2)
-- main :: IO Int
main = do
print (doubleMe 2)
return (doubleMe 2)
-- main :: IO ()
main = do
print (doubleMe 2)
return ()
-- main :: IO ()
main = do
print (doubleMe 2)
-- main :: IO ()
main = print (doubleMe 2)
-- main :: IO ()
main = do
print "Hello"
print (doubleMe 2)
return ()
-- main :: IO String
main = do
print "Hello"
print (doubleMe 2)
return "Hello"
main must be a value of type IO a, and doubleMe 2 has type Int. You probably wanted to print the value:
main = print (doubleMe 2)
It doesn't work because anything using do notation must return a monad. GHCI does some things to make it more useful but it doesn't exactly work like code compiled by GHC.
print :: Show a => a -> IO ()
print takes a value that is an instance of Show and returns an empty IO action. This is most likely what you want to do.
main = print (doubleMe 2)
Should work as probably what you want to do. You don't have the type of the main function defined but in haskell in has to have the type main :: IO (). Looking at the type of doubleMe you can probably see why your code doesn't work.
Your main function takes nothing and returns an integer. You probably want
doubleMe :: Int -> Int
doubleMe x = x + x
main = do
print $ doubleMe 2
which instead outputs 4 to STDOUT.
Congratulations, you have run into Monads. main is an IO monad and must act as such. IO monads do not return Ints. Instead an IO Monad is an IO action, returned by print and executed at runtime.
There are some things happening behind the scenes that make it hard to understand this error message. Here's the reasoning:
Your file doesn't have a module name, so ghc assumes that you are defining module Main.
The name main in module Main has to have type IO something.
But the main you wrote has type Int.
IO something is not the same as Int, no matter what we choose for the something.
GHC only reports the last step.
If you want to print the Int, you can use print to construct an IO action:
main = do
print (doubleMe 2)
This problem doesn't show up in ghci, because there, you can enter expressions of whatever type you want. If the type is IO something, ghci will execute the IO action for you. (Example: readFile "foo.txt"). If the type is not IO something, ghci will add a call to print and then execute that IO action (Example: ['a' .. 'z']).
In a source file, you have to add the call to print yourself if you want it or need it.
Related
This question already has answers here:
How to get normal value from IO action in Haskell
(2 answers)
Closed 1 year ago.
In many imperative programming languages like Java, C or Python we can easily add a print function which can give us information about the intermediate state of the program.
My goal is to find a way to do something like that in Haskell. I want the function which not only computes value but also prints something. The function below is a simplified version of what I want to do. My actual function is too complicated and incomprehensive without context to show it here.
My idea is to have a "pure" Haskell function that has an auxiliary function inside which has [Int] -> IO () -> Int type signature. An IO parameter is initialized in the where clause as a do block. But unfortunately, the do block is not executed, when I run the function in GHCI. The function is compiled successfuly though
module Tests where
-- Function returns the sum of the list and tries to print some info
-- but no IO actually happens
pureFuncWithIO :: [Int] -> Int
pureFuncWithIO [] = 0
pureFuncWithIO nums = auxIOfunc nums (return ())
where
auxIOfunc [] _ = 0
auxIOfunc (n : ns) _ = n + auxIOfunc ns (sneakyIOaction n)
sneakyIOaction n
= do -- Not executed
putStrLn $ "adding " ++ (show n);
return ()
Output in GHCI test:
*Tests> pureFuncWithIO [1,2,3,4,5]
15
Meanwhile, I expected something like this:
*Tests> pureFuncWithIO [1,2,3,4,5]
adding 1
adding 2
adding 3
adding 4
adding 5
15
Is it possible to come up with a way to have IO inside, keeping the return type of the outer-most function, not an IO a flavor? Thanks!
This type signature
pureFuncWithIO :: [Int] -> Int
is promising to the caller that no side effect (like prints) will be observed. The compiler will reject any attempt to perform IO. Some exceptions exist for debugging (Debug.Trace), but they are not meant to be left in production code. There also are some "forbidden", unsafe low-level functions which should never be used in regular code -- you should pretend these do not exist at all.
If you want to do IO, you need an IO return type.
pureFuncWithIO :: [Int] -> IO Int
Doing so allows to weave side effects with the rest of the code.
pureFuncWithIO [] = return 0
pureFuncWithIO (n : ns) = do
putStrLn $ "adding " ++ show n
res <- pureFuncWithIO ns
return (n + res)
A major point in the design of Haskell is to have a strict separation of functions which can not do IO and those who can. Doing IO in a non-IO context is what the Haskell type system was designed to prevent.
Your sneakyIOaction is not executed because you pass its result as a parameter to auxIOfunc, but never use that parameter, and haskell being lazy bastard it is never execute it.
If you try to use said parameter you find out that you can't. It's type not allow you to do anithing with it except combine with other IO things.
There is a way to do what you want, but it is on dark side. You need unsafePerformIO
unsafePerformIO :: IO a -> a
That stuff basically allow you to execute any IO. Tricky thing you have to consume result, otherwise you may end up with haskell skip it due to its laziness. You may want to look into seq if you really want to use it, but don't actually need result.
I checked this post before making this, but that post doesn't really explain why this doesn't work.
foo :: (Num a, Show a) => a -> IO ()
foo 0 = print "Was zero"
foo x = print x
foo 2 -- prints 2
foo 5 -- prints 5
map foo [0..10] :: [IO ()] -- Doesn't print out numbers.
Edit:
bar 0 = foo 0
bar n = do
foo n
bar (n - 1)
I do understand why this returns [IO ()], but I don't understand why the printing doesn't occur while building this list. At the very least, I'd expect that we'd see the first print call occur because of lazy evaluation.
In the process of creating this list, why isn't the 'side effect' of printing to the screen occurring? Is the foo function not actually entered when applied to each element of the list? If the print calls are evaluated to get the IO () to build the list, why doesn't the side effect happen?
map foo [0..10] will definitely construct a list of IO () values, but constructing an IO () value doesn’t execute the IO. You probably know this intuitively: if we have a global IO () and nothing referencing it, it doesn’t get executed:
sayHello :: IO ()
sayHello = putStrLn "hello"
You might attribute that to laziness; after all, if sayHello isn’t referenced, nothing ever forces its evaluation. But then, this doesn’t do anything either:
main = sayHello `seq` return ()
Here, we are certainly evaluating sayHello, but we’re only evaluating an IO ().
What makes an IO do something is when you compose it into another IO (like main) and that gets run, and only then will it do something:
main = sayHello
I should note that GHCi clouds the situation a bit. GHCi has some special interactions with IO: if the overall expression you type at the prompt yields an IO, it will execute it and display the result of that. Otherwise, it just displays the result. But that is just an interactive feature; in real Haskell code, you can’t just have an IO () and expect it to turn into a () magically.
If the print calls are evaluated to get the IO () to build the list, why doesn't the side effect happen?
Because evaluating an expression of type IO () doesn't have any side effects. In fact, evaluating an expression of any type doesn't have any side effects.
The only way to run an IO action is to assign it to main. Evaluating IO actions does not run them.
If you want to call print on the list of values, you must do two things:
First: use mapM_ to build an IO action that prints each value:
mapM_ print [1..3] :: IO ()
Second, assign that expression to main:
main = mapM_ print [1..3]
If you leave out the second step (assign it to something other than main), nothing will happen.
In the IO monad, something like IO a is required. You have [IO ()] which is a list of IO operations. You can use mapM instead, to do a monadic map. mapM f is equivalent to sequence . map f.
I'm trying to do a function which returns true or false.
owlFile = ".+\\.owl"
testOwlFile src = src =~ owlFile :: Bool
And i need to use on my do block :
main = do
[src] <- getArgs
resTestOwlFile <- testOwlFile
if resTestOwlFile
then do ontology <- runX(readDocument [withValidate no,withRemoveWS yes ] src >>> getontology)
else print "error"
But i'm having an error which is Couldn't match excepted type IO BOOL with actual type Bool In the return type of a call of "testOwlFile"
What can i do for that ?
Please avoid, generally, to think about "converting". Sometimes you actually need to do that, but normally the type system gives you just the right type at the right spot if you use it correctly.
IO Bool is not a boolean value, but an action that, possibly together with side effects, will also yield a boolean value. So why would you "convert" a perfectly good pure value to such an action, one that doesn't actually do any of the stuff it's type is there for? That doesn't make much sense. The right thing to do, as already said, is to use the value directly; I'd just put it straight in the if condition:
main = do
[src] <- getArgs
if src =~ owlFile
then ...
else ...
That said, this conversion Bool -> IO Bool, however useless, is certainly possible. Indeed, for any monad1 m, that is one of the fundamental operations:
class Monad m where
return :: a -> m a
So you could in principle write
resTestOwlFile <- return testOwlFile
But don't. That is always equivalent to let resTestOwlFile = testOwlFile (guaranteed by the monad laws).
1
The weaker Applicative is actually sufficient.
The problem is that testOwlFile is of type Bool, but the <- notation expects an IO something.
If testOwlFile did have type IO Bool, then resTestOwlFile would have type Bool and your code would have built fine.
As #user2407038 pointed out in a comment, you can use let instead of <- when the thing you are defining has the same type as the expression you are defining it with:
let resTestOwlFile = testOwlFile
Or you could just use testOwlFile directly in the if statement on the next line.
Note that more generally the <- notation expects m something for any m that's an instance of the Monad class, but in this case m must be IO because you're defining the main function and because of other code in the do block like getArgs and print.
I have problem with reading from file. Whenever I need to read from a file, I do something like this:
main = do x <- readFile "/tmp/foo.txt"
putStr x
But now I would like the path to be an argument, so I tried the following
main s = do x <- readFile s
putStr x
It doesn't work. I see the following error:
Couldn't match expected type `IO t0'
with actual type `FilePath -> IO ()'
In the expression: main
When checking the type of the function `main'
My homework is to write a program and the program has to contain a main function (because it will be compiled) and argument of call must contain the name of the file. I'm not sure I understand this and I don't know how to proceed. I will grateful for some help.
The Haskell report specifies that the main function always has type IO t, (for some type t which will be ignored) and hence never takes normal function arguments, so this is not the right approach.
You are looking for the function getArgs (for which you have to import the module System.Environment. It returns the arguments passed to your program as a list of Strings.
So your code would look like:
import System.Environment
main = do
args <- getArgs
case args of
[file] -> do
x <- readFile file
putStr x
_ -> putStrLn "Wrong number of arguments"
In Haskell, the arguments are NOT given to the main function because of the way Haskell binds its start up and to remain consistent. You need to use System.Environment.getArgs.
In particular, because Haskell is a pure functional language, main is a monadic action that organizes the side-effect-ful computations performed by the software – the result computed by main is discarded, because in functional languages you are detached from the environment w.r.t. computation and only interact with it as a side-effect.
Example
import System.Environment
main = do x <- getArgs; print x
This will print out whatever you type on the command line.
The Haskell wiki has an excellent tutorial on the topic.
So I've been messing around with Haskell, and I've come across this strange error in my code.
" 'IO' is not applied to enough type arguments
Expected kind '?', but 'IO' has kind '->'
In the type signature for 'loop': loop :: State -> IO"
Here is the Code
import System.IO
data State = State [Int] Int Int deriving (Show)
main = do
loop (State [] 0 0)
loop::State -> IO
loop state = do
putStr "file: "
f <- getLine
handle <- openFile f ReadMode
cde <- hGetContents handle
hClose handle
putStrLn cde
loop state
How do I fix this error? Also, any insight on kinds would be greatly appreciated.
IO is a type constructor, which means that it needs an argument in order to become a type. So:
IO Int
IO String
IO ()
are types, but IO by itself is not.
The kind of IO is * -> *, which is like saying it is a function that takes a type and returns a type.
I would suggest changing
loop :: State -> IO
to
loop :: State -> IO ()
(() is the "unit type", it has only one value (also called ()), and is typically used where void would be used in C-like languages)
IO is a type constructor, not a full type. You should declare
loop :: State -> IO ()
where () is the unit type; the type with only one value, also spelled (). That's the appropriate type for an eternal loop or any other function that does not return a (meaningful) value.
As others have mentioned, IO is a type constructor, not a type. So you have to apply it to some other type. A value of type IO Foo means that it is a computation which potentially does some I/O and then returns a value of type Foo.
luqui and larsman suggested that you should use () as a return value. I think the following type is a better alternative for a function that loops forever:
loop :: String -> IO a
Note that the function now is polymorphic in the return value. This type is much more informative than having it return (). Why? Because a function of this type must be a looping function. There is no way to implement a terminating function with this type. A user of this function will see immediately from the type that it is a looping function. So you get some documentation for free with this type.