I'm trying to learn Haskell and the small bit of sample code I tried to understand is compiling, but while applying the code I was running into a "Couldn't match expected type" error. Can anyone give me some guidance as to what I'm doing wrong/how I should go about this?
This code was given in a lecture:
> mult :: Integer -> (Integer, Integer-> Integer )
> mult x = (x,(*x))
Executing snd (mult 3) 5
as I was told in the lecture I get
15
However when executing (mult 3) 5
I get the following error
<interactive>:133:1: error:
• Couldn't match expected type ‘Integer -> t’
with actual type ‘(Integer, Integer -> Integer)’
• The function ‘mult’ is applied to two arguments,
but its type ‘Integer -> (Integer, Integer -> Integer)’
has only one
In the expression: (mult 3) 5
In an equation for ‘it’: it = (mult 3) 5
• Relevant bindings include it :: t (bound at <interactive>:133:1)
Seeing the error I have tried to apply mult
with one argument mult 3
which resulted in the following error
<interactive>:135:1: error:
• No instance for (Show (Integer -> Integer))
arising from a use of ‘print’
(maybe you haven't applied a function to enough arguments?)
• In a stmt of an interactive GHCi command: print it
Why can't I use mult
without the snd
function?
CodePudding user response:
(Integer, Integer -> Integer)
This is not a function. It might look kind of like a function of two arguments, but it's actually parenthesized as (Integer, (Integer -> Integer))
so it's a tuple, where the first thing is just an ordinary number and the second is a function.
mult :: Integer -> (Integer, Integer -> Integer)
mult x = (x, (*x))
Here, we take a number x
and return a 2-tuple. The first element of this tuple is just the number x
, nothing more and nothing less. The second element is a function which multiplies by x
. These are two distinct values, not tied together in any way.
fst (mult 3)
This is the first element of the tuple, which is just a number. In this case, we'll get 3
.
snd (mult 3)
This is the second element of the tuple, a function from Integer
to Integer
. We can't print out functions in Haskell (since they don't implement Show
), so we have to apply it to an argument in order to get a result.
snd (mult 3) 5 -- Or, equivalently, (snd (mult 3)) 5
This applies the function "multiply by 3" to the number 5, so we get 5 times 3, or 15
.
(mult 3) 5
This takes a tuple mult 3
(whose value is (x, (* x))
), and attempts to apply it to a number. In Haskell, only functions can be given arguments, and a tuple is not a function, so you get an error that basically says "I expected a function here, but I got a tuple".
CodePudding user response:
Why can't I use
mult
without thesnd
function?
Because mult 5
returns a 2-tuple, it returns (5, (* 5))
, so the first item is an Integer
whereas the second is a function with type Integer -> Integer
.
You can not use this 2-tuple as a function when you apply 3
to it. What would the result of (5, (* 5)) 3
be? By using snd (5, (* 5))
it returns (* 5)
, and then you can use that for (* 5) 3
, which is 15
.
Furthermore you can not use show f
with f
a function, since for a generic function, that can not produce output. Using printing the result of mult 3
is thus not possible, you can print fst (mult 3)
for example, which is 3
.