Haskell - passing a function as a argument compilation error - haskell

I have a very simple function called 'fold' that takes a function f and executes it. Given a function 'add' and two numbers it calls add with those two numbers and displays the results. However I cannot compile it due to a compilation error below. What is the error specifically stating and what can I do to solve it?
module Main where
add x y = x + y
--fold :: ((a,b)->c) -> a->b->c
fold f n x = f n x
main :: IO ()
main = do
fold add 2 3

The problem is that you've declared main (correctly) as having type IO (), but fold doesn't return that. The error message is a little more complicated because in theory, add (and thus fold) could return a value of type IO (), since add can return any type with a Num instance. IO (), however, is not an instance of Num. The solution is to return an IO action created from the return value of fold. One way to do that is to use the print function (which takes any value with a Show instance and converts it to a String before outputing it).
main = print $ fold add 2 3

Related

What is the IO type in Haskell

I am new to the Haskell programming language, I keep on stumbling on the IO type either as a function parameter or a return type.
playGame :: Screen -> IO ()
OR
gameRunner :: IO String -> (String -> IO ()) -> Screen -> IO ()
How does this work, I am a bit confused because I know a String expects words and an Int expects numbers. Whats does the IO used in functions expect or Return?
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. Because of this side effect, an IO action is not referentially transparent; therefore, execution order matters. It is the task of the main function of a Haskell program to properly sequence and execute all IO actions. Thus, when you write a function that returns IO a, what you are actually doing is writing a function that returns an action that eventually - when executed by main - performs the action and returns an a.
Some more explanation:
Referential transparency means that you can replace a function by its value. A referentially transparent function cannot have any side effects; in particular, a referentially transparent function cannot access any hardware resources like files, network, or keyboard, because the function value would depend on something else than its parameters.
Referentially transparent functions in a functional language like Haskell are like math functions (mappings between domain and codomain), much more than a sequence of imperative instructions on how to compute the function's value. Therefore, Haskell code says the compiler that a function is applied to its arguments, but it does not say that a function is called and thus actually computed.
Therefore, referentially transparent functions do not imply the order of execution. The Haskell compiler is free to evaluate functions in any way it sees fit - or not evaluate them at all if it is not necessary (called lazy evaluation). The only ordering arises from data dependencies, when one function requires the output of another function as input.
Real-world side effects are not referentially transparent. You can think of the real world as some sort of implicit global state that effectual functions mutate. Because of this state, the order of execution matters: It makes a difference if you first read from a database and then update it, or vice versa.
Haskell is a pure functional language, all its functions are referentially transparent and compilation rests on this guarantee. How, then, can we deal with effectful functions that manipulate some global real-world state and that need to be executed in a certain order? By introducing data dependency between those functions.
This is exactly what IO does: Under the hood, the IO type wraps an effectful function together with a dummy state paramter. Each IO action takes this dummy state as input and provides it as output. Passing this dummy state parameter from one IO action to the next creates a data dependency and thus tells the Haskell compiler how to properly sequence all the IO actions.
You don't see the dummy state parameter because it is hidden behind some syntactic sugar: the do notation in main and other IO actions, and inside the IO type.
Briefly put:
f1 :: A -> B -> C
is a function which takes two arguments of type A and B and returns a C. It does not perform any IO.
f2 :: A -> B -> IO C
is similar to f1, but can also perform IO.
f3 :: (A -> B) -> IO C
takes as an argument a function A -> B (which does not perform IO) and produces a C, possibly performing IO.
f4 :: (A -> IO B) -> IO C
takes as an argument a function A -> IO B (which can perform IO) and produces a C, possibly performing IO.
f5 :: A -> IO B -> IO C
takes as an argument a value of type A, an IO action of type IO B, and returns a value of type C, possibly performing IO (e.g. by running the IO action argument one or more times).
Example:
f6 :: IO Int -> IO Int
f6 action = do
x1 <- action
x2 <- action
putStrLn "hello!"
x3 <- action
return (x1+x2+x3)
When a function returns IO (), it returns no useful value, but can perform IO. Similar to, say, returning void in C or Java. Your
gameRunner :: IO String -> (String -> IO ()) -> Screen -> IO ()
function can be called with the following arguments:
arg1 :: IO String
arg1 = do
putStrLn "hello"
s <- readLine
return ("here: " ++ s)
arg2 :: String -> IO ()
arg2 str = do
putStrLn "hello"
putStrLn str
putStrLn "hello again"
arg3 :: Screen
arg3 = ... -- I don't know what's a Screen in your context
Let's try answering some simpler questions first:
What is the Maybe type in Haskell?
From chapter 21 (page 205) of the Haskell 2010 Report:
data Maybe a = Nothing | Just a
it's a simple partial type - you have a value (conveyed via Just) or you don't (Nothing).
How does this work?
Let's look at one possible Monad instance for Maybe:
instance Monad Maybe where
return = Just
Just x >>= k = k x
Nothing >>= _ = Nothing
This monadic interface simplifies the use of values based on Maybe constructors e.g.
instead of:
\f ox oy -> case ox of
Nothing -> Nothing
Just x -> case oy of
Nothing -> Nothing
Just y -> Just (f x y)
you can simply write this:
\f ox oy -> ox >>= \x -> oy >>= \y -> return (f x y)
The monadic interface is widely applicable: from parsing to encapsulated state, and so much more.
What does the Maybe type used in functions expect or return?
For a function expecting a Maybe-based value e.g:
maybe :: b -> (a -> b) -> Maybe a -> b
maybe _ f (Just x) = f x
maybe d _ Nothing = d
if its contents are being used in the function, then the function may have to deal with not receiving a value it can use i.e. Nothing.
For a function returning a Maybe-based value e.g:
invert :: Double -> Maybe Double
invert 0.0 = Nothing
invert d = Just (1/d)
it just needs to use the appropriate constructors.
One last point: observe how Maybe-based values are used - from starting simply (e.g. invert 0.5 or Just "here") to then define other, possibly more-elaborate Maybe-based values (with (>>=), (>>), etc) to ultimately be examined directly by pattern-matching, or abstractly by a suitable definition (maybe, fromJust et al).
Time for the original questions:
What is the IO type in Haskell?
From section 6.1.7 (page 75) of the Report:
The IO type serves as a tag for operations (actions) that interact with the outside world. The IO type is abstract: no constructors are visible to the user. IO is an instance of the Monad and Functor classes.
the crucial point being:
The IO type is abstract: no constructors are visible to the user.
No constructors? That begs the next question:
How does this work?
This is where the versatility of the monadic interface steps in: the flexibility of its two key operatives - return and (>>=) in Haskell - substantially make up for IO-based values being
abstract.
Remember that observation about how Maybe-based values are used? Well, IO-based values are used in similar fashion - starting simply (e.g. return 1, getChar or putStrLn "Hello, there!") to defining other IO-based values (with (>>=), (>>), catch, etc) to ultimately form Main.main.
But instead of pattern-matching or calling another function to extract its contents, Main.main is
processed directly by the Haskell implementation.
What does the IO used in functions expect or return?
For a function expecting a IO-based value e.g:
echo :: IO ()
echo :: getChar >>= \c -> if c == '\n'
then return ()
else putChar c >> echo
if its contents are being used in the function, then the function usually returns an IO-based value.
For a function returning a IO-based value e.g:
newLine :: IO ()
newLine = putChar '\n'
it just needs to use the appropriate definitions.

Equations for `someFunction' have different numbers of arguments

I'm using in order to practice/learn Haskell. I'm having trouble understanding why a given situation works on my example local code, and doesn't work on CodeWars.
On codewars:
module Codewars.Kata.Negative where
makeNegative :: (Num a) => a -> a
makeNegative x = x + x
makeNegative = error "todo: makeNegative"
This gives me:
Codewars/Kata/Negative.hs:4:1:
Equations for `makeNegative' have different numbers of arguments
Codewars/Kata/Negative.hs:4:1-22
Codewars/Kata/Negative.hs:5:1-41
But when I test it locally:
import Data.List
import System.IO
example :: (Num a) => a -> a
example x = x + x
main = do
print (example(3))
It returns 6 properly. I can't even try to solve the problem because the compiler complains about the arguments. I kinda got it that Num is a "typeclass", but I don't get how that works differently on codewars. I guess its because of that "where" clause there.
The problem lies in your definition of makeNegative. Notice there's three lines of the definition:
makeNegative :: (Num a) => a -> a
makeNegative x = x + x
makeNegative = error "todo: makeNegative"
The first is the type signature, followed by two definitions. Oftentimes multiple definitions are provided when pattern matching on arguments and handling different cases; however in this case the pattern match will never fail; so the error line will never run.
Regardless of the fact that it will never be run; Haskell still requires that all implementations of a function have the same number of bound arguments, makeNegative x = binds one argument (namely x); but the second definition makeNegative = doesn't bind any arguments. In this case it looks like it's a placeholder definition so you can just delete the line with error and it should work.
Your example test only has a single definition, so it doesn't run into this issue.

simple function error "Variable not in scope" haskell

I have just started to code Haskell today, stuck on building function that takes an integer from user, multiply it by 3, adds one and checks if it is Even. returns the output as Boolean, true if even.
Sorry if the code is too faulty, I'm a Haskell newbie.
checkIfEven :: Int -> Bool
x <- readLn
let checkIfEven x = (even ((x*3)+1))
print checkIfEven
error:
Variable not in scope: checkIfEven :: Int -> Bool
I/O has to be handled explicitly in Haskell, as readLn is not a function; it's an IO action. It is simpler to start with a true function that takes the value to check as an argument:
checkIfEven :: Int -> Bool
checkIfEven x = even (x*3 + 1)
Note that the parentheses are not part of the call to even, but rather "grouping" the expression x * 3 + 1, as even x*3 + 1 is parsed as (even x) * 3 + 1.
Now that we have a pure function, we can apply it to a value input by the user.
program :: IO Bool
program = do
x <- readLn
return (checkIfEven (read x))
A few things to note:
<- is not an assignment operator; it's special syntax inside a do construct with "extracts" a value from (in this context) an IO action.
x will be a string, so you need to parse it to get an Int value for checkIfEven. read is a simple way to do that; we're ignoring the possibility that the user may enter a string that can not be parsed as an Int.
return doesn't return a value from a function (note we did not use it in the definition of checkIfEven. Rather, it "lifts" a value into a new IO action, has program has to be value of type IO Bool, not Bool.
Note that a do construct provides an imperative-looking way to work with IO actions. You can work directly with the underlying functions and values; in this case, we could have simply written
program = fmap (checkIfEven . read) readLn
The full explanation of how IO (and monads in general) work is beyond the scope of this question; hopefully, this will give you an idea of what to focus on as you study the topic further.

Type class Read, is it posibble to read a function by it name?

Suppose I have this function:
squared x = x ** 2
and I want to read it from the console, and apply it. Is possible to do something like this?:
gchi> (read("squared) :: Int -> Int) 4
No; in general, this is not possible. To see why, think about a few of the situations which could occur if this functionality existed:
Let’s say you redefine (+) a b = a - b. Now, should read "(+)" be the (+) from the Prelude, or your redefined (+) operator?
If you do read "foobar", and foobar has not yet been defined as a function, then what should this return? Then if foobar is defined somewhere else in the module, should this return value suddenly change?
If you add import Prelude () to the top of your program, which removes all of the imports from Prelude, should read "preludeFunctionName" stop working?
Now, none of these problems are dealbreakers in and of themselves — in another language, you could still define a read function taking those into account. The problem in this case is referential transparency : the property that a non-IO function should always return the same output given the same input(s). Since the type of read is Read a => String -> a, as opposed to Read a => String -> IO a, you can’t make an instance of read like you want, given that the above function can give a different answer depending on the exact context in which it is run. (e.g. read "foobar" and let foobar = (+1) in read "foobar" would give different answers to the same function call.)
On the other hand, if you still want to have this functionality, there is one way of getting it. The hint package allows Haskell code to be interpreted at runtime, and so you can use this functionality to write a function like this:
-- Warning: the following code is untested
-- Please comment if you find any errors!
import Language.Haskell.Interpreter
readFn :: Typeable a
=> [ModuleName] -- ^ Modules to search
-> String -- ^ Function to read
-> a -- ^ Witness for the type a
-> IO (Either InterpreterError a)
readFn m f w = runInterpreter $ do
setImports m
interpret f w
The above function can be used as follows:
readFn ["Prelude"] "(+)" (as :: Num a => a -> a -> a)
Where as is from Language.Haskell.Interpreter.

What monadic type return return function

This function is strange. I'm confused.
return :: (Monad m) => a -> m a
If i wrote return 5, I will get monad with 5 inside. But what type? Typeclasses are only named dependencies, not types. Monad is List, IO ... but this is undefined monad type.
return is polymorphic so it can stand for more than one type. Just like + in C is overloaded to work both at summing ints and at summing floats, return is overloaded to work with any monad.
Of course, when its time to run the code you need to know what type the m corresponds to in order to know what concrete implementation of return to use. Some times you have explicit type annotations or type inference that lets you know what implementation of return to use
(return 5) :: [Int]
Other times, you can "push up" the decision higher up. If you write a larger polymorphic function, the inner returns use the same type from the outer function.
my_func :: Monad m => a -> m a
my_func x = return x
(my_func 10) :: [Int]
I told my func that I was working on the list monad and in turn, this made my_func use the list monad implementation of return inside.
Finally, if you don't leave enough information for the compiler to figure out what type to use, you will get an ambiguou intance compilation error. This is specially common with the Read typeclass. (try typing x <- readLn in ghci to see what happens...)
It's polymorphic. It returns whatever monad instance's return implementation was called. What specific data type it returns depends on the function.
[1,2,3] >>= \n -> return $ n + 1 -- Gives [2,3,4]
getLine >>= \str -> return $ reverse str -- Gets input and reverses it

Resources