Please bear with me as I am very new to functional programming and Haskell. I am attempting to write a function in Haskell that takes a list of Integers, prints the head of said list, and then returns the tail of the list. The function needs to be of type [Integer] -> [Integer]. To give a bit of context, I am writing an interpreter and this function is called when its respective command is looked up in an associative list (key is the command, value is the function).
Here is the code I have written:
dot (x:xs) = do print x
return xs
The compiler gives the following error message:
forth.hs:12:1:
Couldn't match expected type `[a]' against inferred type `IO [a]'
Expected type: ([Char], [a] -> [a])
Inferred type: ([Char], [a] -> IO [a])
In the expression: (".", dot)
I suspect that the call to print in the dot function is what is causing the inferred type to be IO [a]. Is there any way that I can ignore the return type of print, as all I need to return is the tail of the list being passed into dot.
Thanks in advance.
IO is the way how Haskell differentiates between code that is referentially transparent and code that is not. IO a is the type of an IO action that returns an a . You can think of an IO action as a piece of code with some effect on the real world that waits to get executed.
return is actually just a simple function in Haskell. It does not return something. It wraps a value into a monad. Looks like return is an overloaded function.
The print function outputs a value of any printable type to the standard output device. Printable types are those that are instances of class Show; print converts values to strings for output using the show operation and adds a newline.
In most functional languages, this would work. However, Haskell is a pure functional language. You are not allowed to do IO in functions, so the function can either be
[Int] -> [Int]
without performing any IO or[Int] -> IO [Int]
with IOThe type of dot
as inferred by the compiler is dot :: (Show t) => [t] -> IO [t]
but you can declare it to be [Int] -> IO [Int]
:
dot :: [Int] -> IO [Int]
See IO monad: http://book.realworldhaskell.org/read/io.html
I haven't mentioned System.IO.Unsafe.unsafePerformIO
that should be used with great care and with a firm understanding of its consequences.
No, either your function causes side effects (aka IO, in this case printing on the screen), or it doesn't. print
does IO and therefore returns something in IO
and this can not be undone.
And it would be a bad thing if the compiler could be tricked into forgetting about the IO
. For example if your [Integer] -> [Integer]
function is called several times in your program with the same parameters (like []
for example), the compiler might perfectly well just execute the function only once and use the result of that in all the places where the function got "called". Your "hidden" print would only be executed once even though you called the function in several places.
But the type system protects you and makes sure that all function that use IO
, even if only indirectly, have an IO
type to reflect this. If you want a pure function you cannot use print
in it.
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