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.
Related
In Haskell, the type constructor IO is a monad equipped with a return statement that lifts any expression to its IO version.
Nothing prevents us from lifting what is already an IO action to its IO version - giving us a type of the form IO (IO a).
So I can for example write the following program:
main = return . print $ "Hello world"
Which upon execution does exactly nothing.
My question is, what happens under the hood when this main is executed?
Are there any situations where it makes sense to return an IO action?
Under the hood, the runtime effectively discards the result of the IO action main, which is why it is usually defined as IO (). This means that if main actually has a type like IO (IO Int), there is no real issue. The IO action is executed, and the result (another IO action) is discarded, unexecuted.
Deeper in your program, you are more likely to just trigger a type error. For example, fmap doSomething (return . getLine) won't type-check if you meant fmap doSomething getLine.
IO is often approximated to State RealWorld, that is a State monad that operates on the "real world". return for State produces an action that does not alter contained state. So, by analogy, returning anything to IO doesn't do anything as well. Not only when you return some IO a, but any a.
Returning an IO action may be used to build up a computation in one place (capturing some values into a closure along the way) and execute it somewhere else. Much like passing a callback in C.
Actually, to build up an IO computation and pass it somewhere else you can use a let inside of a do-block:
main :: IO ()
main = do
let act = readFile "somefile" -- action is not performed yet
foo act -- pass the action as a parameter
foo :: IO () -> IO ()
foo act = do
.. do something
result <- act -- actually perform the action
..
In this case you don't need to return an IO a value.
But if the process of building that computation itself requires you to perform IO actions, that's where you'd need such a thing. In our example, let's ask user of filename to be opened:
main :: IO ()
main = do
act <- do
filename <- getLine
return (readFile filename)
foo act
Here, we need a filename to create our action, but getLine is in IO as well. That's where additional level of IO comes out. Of course, this example is synthetic, as you can just do filename <- getLine right in main.
I wrote a bunch of code in Haskell to create an index of a text. The top function looks like this:
index :: String -> [(String, [Integer])]
index a = [...]
Now I want to give this function a String read from a file:
index readFile "input.txt"
Which won't work because readFile is of type FilePath -> IO String.
Couldn't match expected type 'String'
against inferred type 'IO String'
I see the error, but I can't find any function with type:
IO String -> String
I guess the key to success lies somewhere under some Monads, but I could not find a way to solve my problem.
You can easily enough write a function that calls the readFile action, and passes the result to your index function.
readAndIndex fileName = do
text <- readFile fileName
return $ index text
However, the IO monad taints everything that uses it, so this function has the type:
readAndIndex :: FilePath -> IO [(String, [Integer])]
There is a very good reason why there is no such function.
Haskell has the notion of functional purity. This means that a function will always return the same result when called with the same parameters. The only place where IO is allowed is inside the IO monad.
If there was* a function
index :: IO String -> String
then we could suddenly do IO actions anywhere by calling, for example:
index (launchMissiles >> deleteRoot >> return "PWNd!")
Functional purity is a very useful feature that we don't want to lose, since it allows the compiler to reorder and inline functions much more freely, they can be sparked off to different cores without changing the semantics and it also gives the programmers a sense of security since if you can know what a function can and can't do from it's type.
* Actually there is such a function. It's called unsafePerformIO and it's called that for very, very good reasons. Do not use it unless you're 100% sure of what you are doing!
Well you cannot get rid of the IO monad part of IO String. That means you will have to make your function return IO [(String, [Integer])].
I recommend learning more about monads, but for now you can get away with the liftM function:
liftM index (readFile "input.txt")
liftM has this signature:
liftM :: Monad m => (a -> b) -> m a -> m b
It takes a non-monadic function and transforms it into a monadic function.
fmap index $ readFile "input.txt"
or
readFile "input.txt" >>= return . index
You may want to look into monad and functors
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 want to write functions and put result to string.
I want function:
read' :: FilePath -> String
I use:
:t readFile
readFile :: FilePath -> IO String
I make:
read' :: IO ()
read' = do
str <- readFile "/home/shk/workspace/src/test.txt"
putStrLn str
I want to ask str is string or not?
We know that:
:t putStrLn
putStrLn :: String -> IO ()
Then why i can't:
read' :: String
read' = do
str <- readFile "/home/shk/workspace/lxmpp/src/test.txt"
str
I get error that:
Couldn't match expected type `[t0]' with actual type `IO String'
In the return type of a call of `readFile'
In a stmt of a 'do' expression:
str <- readFile "/home/shk/workspace/lxmpp/src/test.txt"
In the expression:
do { str <- readFile "/home/shk/workspace/src/test.txt";
str }
Thank you.
Just to quibble a bit more, while the other answers are perfectly correct, I want to emphasize something: Something with the type IO String isn't just a string that the type system won't let you get at directly. It's a computation that performs I/O to get a string for you. Applying readFile to a file path doesn't return a String value any more than putting a steak next to a meat grinder magically turns them into a hamburger.
When you have some code like this:
foo = do let getStr = readFile "input.txt"
s1 <- getStr
s2 <- getStr
-- etc.
That doesn't mean you're "taking the string out of getStr twice". It means you're performing the computation twice and can easily get different results between the two.
I think no one has answered this, very important question, yet:
I want to ask str is string or not?
I will try to.
The type of the variable str is String, yes.
However, the scope of this variable is very limited. I think desugaring the do-notation is necessary for understanding:
read' = readFile "/home/shk/workspace/src/test.txt" >>= (\str -> putStrLn str)
I think here it becomes more clear why str is not good enough. It is an argument of the function you pass to >>=. Its value only becomes available when someone calls your function, which happens only when the IO action containing it is being executed.
Also, the type of read' :: IO () is determined not so much by the putStrLn str, but rather by the return type of the operator >>=. Have a look at it (specialized to the IO monad):
(>>=) :: IO a -> (a -> IO b) -> IO b
You can see that the result is always an IO b action, so trying to change any of arguments won't help.
You can read some monad tutorial if you want to understand why the type is the way it is. The intuition behind it is: you can't perform an action without performing an action.
And on the practical side of the question, to use the value returned by some action, instead of trying to do use (extractValue inputAction), which does not make sense because extractValue is not possible, try inputAction >>= use if your use does involve I/O, or fmap use inputAction if it does not.
You should use return str in read' if you want it to return str instead of (). You can't strip IO from the type of read', since it's not a pure function. To get a better grip on how input/output in Haskell works I recommend you to read a tutorial.
As a more detailed reason why: It allows impurity.
You absolutely can not perform IO during a pure operation, or it would completely break referential transparency. Technically you can use unsafePerformIO but it would break referential transparency in this case - you should only use that if you can guarantee that the result is always the same.
I wrote a bunch of code in Haskell to create an index of a text. The top function looks like this:
index :: String -> [(String, [Integer])]
index a = [...]
Now I want to give this function a String read from a file:
index readFile "input.txt"
Which won't work because readFile is of type FilePath -> IO String.
Couldn't match expected type 'String'
against inferred type 'IO String'
I see the error, but I can't find any function with type:
IO String -> String
I guess the key to success lies somewhere under some Monads, but I could not find a way to solve my problem.
You can easily enough write a function that calls the readFile action, and passes the result to your index function.
readAndIndex fileName = do
text <- readFile fileName
return $ index text
However, the IO monad taints everything that uses it, so this function has the type:
readAndIndex :: FilePath -> IO [(String, [Integer])]
There is a very good reason why there is no such function.
Haskell has the notion of functional purity. This means that a function will always return the same result when called with the same parameters. The only place where IO is allowed is inside the IO monad.
If there was* a function
index :: IO String -> String
then we could suddenly do IO actions anywhere by calling, for example:
index (launchMissiles >> deleteRoot >> return "PWNd!")
Functional purity is a very useful feature that we don't want to lose, since it allows the compiler to reorder and inline functions much more freely, they can be sparked off to different cores without changing the semantics and it also gives the programmers a sense of security since if you can know what a function can and can't do from it's type.
* Actually there is such a function. It's called unsafePerformIO and it's called that for very, very good reasons. Do not use it unless you're 100% sure of what you are doing!
Well you cannot get rid of the IO monad part of IO String. That means you will have to make your function return IO [(String, [Integer])].
I recommend learning more about monads, but for now you can get away with the liftM function:
liftM index (readFile "input.txt")
liftM has this signature:
liftM :: Monad m => (a -> b) -> m a -> m b
It takes a non-monadic function and transforms it into a monadic function.
fmap index $ readFile "input.txt"
or
readFile "input.txt" >>= return . index
You may want to look into monad and functors