Confusion with function composition - function

Beginning to learn Haskell:
*Main> map double [1,2,3]
[2,4,6]
*Main> sum (map double [1,2,3])
12
*Main> (sum . map) (double) ([1,2,3])
<interactive>:71:8:
Couldn't match type ‘[b0] -> [b0]’ with ‘[[t0] -> t]’
Expected type: (b0 -> b0) -> [[t0] -> t]
Actual type: (b0 -> b0) -> [b0] -> [b0]
Relevant bindings include it :: t (bound at <interactive>:71:1)
Probable cause: ‘map’ is applied to too few arguments
In the second argument of ‘(.)’, namely ‘map’
In the expression: sum . map
According to this answer: Haskell: difference between . (dot) and $ (dollar sign) "The primary purpose of the . operator is not to avoid parenthesis, but to chain functions. It lets you tie the output of whatever appears on the right to the input of whatever appears on the left.".
OK, so why my example does not work? Actual and expected types are different, but why? After all, according to this description map should take (double) ([1,2,3]) on the input and pass its output to sum's input?

The reason for this is that . only allows the function to take one argument before being passed to the next. So:
(sum . map) double [1,2,3]
Will become
(sum (map double)) [1,2,3]
...and we can't sum a function, can we? Type error galore!
What you'll want to do is this:
(sum . map double) [1,2,3]
which reduces to:
sum (map double [1,2,3])
If you want to see, here's how . is defined:
(.) :: (b -> c) -> (a -> b) -> (a -> c)
(.) f g arg = f (g arg)
If you're being really smart, you can doubly compose something, so that it takes two arguments before it's passed along:
((sum .) . map) double [1,2,3]
which reduces to:
(sum . map double) [1,2,3]
and finally:
sum (map double [1,2,3])

Related

Type mismatch on basic "apply twice" hello world in Haskell

The minimal code:
twice :: (a -> a) -> a -> a
twice f = f . f
main = do
return twice ++ "H"
The errors generated:
stack runhaskell "c:\Users\FruitfulApproach\Desktop\Haskell\test.hs"
C:\Users\FruitfulApproach\Desktop\Haskell\test.hs:5:1: error:
* Couldn't match expected type `IO t0'
with actual type `[(a0 -> a0) -> a0 -> a0]'
* In the expression: main
When checking the type of the IO action `main'
|
5 | main = do
| ^
C:\Users\FruitfulApproach\Desktop\Haskell\test.hs:6:20: error:
* Couldn't match type `Char' with `(a -> a) -> a -> a'
Expected type: [(a -> a) -> a -> a]
Actual type: [Char]
* In the second argument of `(++)', namely `"H"'
In a stmt of a 'do' block: return twice ++ "H"
In the expression: do return twice ++ "H"
* Relevant bindings include
main :: [(a -> a) -> a -> a]
(bound at C:\Users\FruitfulApproach\Desktop\Haskell\test.hs:5:1)
|
6 | return twice ++ "H"
| ^^^
How would I logically fix this issue myself? Clearly it's something I'm doing wrong. Am I missing a preamble that every example should have?
As RobinZigmond mentions in the comments, you can’t write twice ++ "H". This means, ‘take the function twice, and append the string "H" to it’. This is clearly impossible, since ++ can only append strings and lists together. I suspect that what you meant was twice (++ "H"). This takes the function (++ "H"), which appends "H" to the end of its argument, and runs it twice.
But even if you do this, there is still a problem. Take a look at the program which is created if you do this:
twice :: (a -> a) -> a -> a
twice f = f . f
main = do
return (twice (++ "H"))
Even though this program compiles, it doesn’t do anything! You have set twice (++ "H")) as the return value of main, but the return value of main is always ignored. In order to produce output, you need to use putStrLn instead of return:
twice :: (a -> a) -> a -> a
twice f = f . f
main = do
putStrLn (twice (++ "H"))
But this program doesn’t work either! twice (++ "H") is a function, which cannot be printed. This function must be applied to a value in order to produce a result:
twice :: (a -> a) -> a -> a
twice f = f . f
main = do
putStrLn (twice (++ "H") "Starting value")
This program should finally work, giving an output of Starting valueHH when it is run.

Function for defining vector doesn't work in Haskell

I'm beginner in Haskell (currently learning pattern matching) and I tried to write simple function for defining vector:
vector :: (Num a) => a -> a -> String
vector 0 0 = "This vector has 0 magnitude."
vector x y = "This vector has a magnitude of " ++ show(sqrt(x^2 + y^2)) ++ "."
But I get bunch of errors which I don't understand at all.
helloworld.hs:9:8: error:
• Could not deduce (Eq a) arising from the literal ‘0’
from the context: Num a
bound by the type signature for:
vector :: Num a => a -> a -> String
at helloworld.hs:8:1-37
Possible fix:
add (Eq a) to the context of
the type signature for:
vector :: Num a => a -> a -> String
• In the pattern: 0
In an equation for ‘vector’:
vector 0 0 = "This vector has 0 magnitude."
helloworld.hs:10:51: error:
• Could not deduce (Show a) arising from a use of ‘show’
from the context: Num a
bound by the type signature for:
vector :: Num a => a -> a -> String
at helloworld.hs:8:1-37
Possible fix:
add (Show a) to the context of
the type signature for:
vector :: Num a => a -> a -> String
• In the first argument of ‘(++)’, namely
‘show (sqrt (x ^ 2 + y ^ 2))’
In the second argument of ‘(++)’, namely
‘show (sqrt (x ^ 2 + y ^ 2)) ++ "."’
In the expression:
"This vector has a magnitude of "
++ show (sqrt (x ^ 2 + y ^ 2)) ++ "."
helloworld.hs:10:56: error:
• Could not deduce (Floating a) arising from a use of ‘sqrt’
from the context: Num a
bound by the type signature for:
vector :: Num a => a -> a -> String
at helloworld.hs:8:1-37
Possible fix:
add (Floating a) to the context of
the type signature for:
vector :: Num a => a -> a -> String
• In the first argument of ‘show’, namely ‘(sqrt (x ^ 2 + y ^ 2))’
In the first argument of ‘(++)’, namely
‘show (sqrt (x ^ 2 + y ^ 2))’
In the second argument of ‘(++)’, namely
‘show (sqrt (x ^ 2 + y ^ 2)) ++ "."’
Failed, modules loaded: none.
Prelude> :load helloworld
[1 of 1] Compiling Main ( helloworld.hs, interpreted )
helloworld.hs:10:51: error:
• Could not deduce (Show a) arising from a use of ‘show’
from the context: Integral a
bound by the type signature for:
vector :: Integral a => a -> a -> String
at helloworld.hs:8:1-42
Possible fix:
add (Show a) to the context of
the type signature for:
vector :: Integral a => a -> a -> String
• In the first argument of ‘(++)’, namely
‘show (sqrt (x ^ 2 + y ^ 2))’
In the second argument of ‘(++)’, namely
‘show (sqrt (x ^ 2 + y ^ 2)) ++ "."’
In the expression:
"This vector has a magnitude of "
++ show (sqrt (x ^ 2 + y ^ 2)) ++ "."
helloworld.hs:10:56: error:
• Could not deduce (Floating a) arising from a use of ‘sqrt’
from the context: Integral a
bound by the type signature for:
vector :: Integral a => a -> a -> String
at helloworld.hs:8:1-42
Possible fix:
add (Floating a) to the context of
the type signature for:
vector :: Integral a => a -> a -> String
• In the first argument of ‘show’, namely ‘(sqrt (x ^ 2 + y ^ 2))’
In the first argument of ‘(++)’, namely
‘show (sqrt (x ^ 2 + y ^ 2))’
In the second argument of ‘(++)’, namely
‘show (sqrt (x ^ 2 + y ^ 2)) ++ "."’
Failed, modules loaded: none.
Can somebody explain me how to write this function properly, at least what's wrong with vector 0 0?
The first type error is because you're pattern matching on the literal 0. You've only required Num a where you needed (Num a, Eq a) in order for this to be possible.
The second type error is because you've tried to use show on a computation involving your a. So now, you need (Num a, Eq a, Show a).
The third, because you've used sqrt, which does not reside in Num but in Floating, so now it's (Num a, Eq a, Show a, Floating a).
Alternatively, you could have just removed the type signature entirely and prompted ghci for the type:
λ> :t vector
vector :: (Show a, Floating a, Eq a) => a -> a -> [Char]
Note that Floating implies Num.
The error messages tell you everything you need to know.
Could not deduce (Eq a)
When you use a pattern-match on a numeric literal, it needs the constraints (Eq a, Num a) because Haskell uses == internally to do matching on literals.
Could not deduce (Show a)
When you use show, you need the constraint (Show a), because not all types are showable by default.
Could not deduce (Floating a)
When you use fractional operations such as sqrt, you need the constraint (Floating a), because not all numeric types support these operations.
Putting it all together:
vector :: (Eq a, Num a, Show a, Floating a) => a -> a -> String
vector 0 0 = "This vector has 0 magnitude."
vector x y = "This vector has a magnitude of " ++ show(sqrt(x^2 + y^2)) ++ "."
You could also leave off the type signature, then ask ghci:
> let vector 0 0 = "This vector has 0 magnitude."; vector x y = "This vector has a magnitude of " ++ show(sqrt(x^2 + y^2)) ++ "."
> :t vector
vector :: (Eq a, Floating a, Show a) => a -> a -> [Char]
And here you can see that you don’t need the extra Num a constraint, because Floating is a subclass of Num, by way of Fractional. You can get information on these classes in ghci as well:
> :info Floating
class Fractional a => Floating a where
pi :: a
exp :: a -> a
log :: a -> a
sqrt :: a -> a
...
-- Defined in ‘GHC.Float’
instance Floating Float -- Defined in ‘GHC.Float’
instance Floating Double -- Defined in ‘GHC.Float’
When writing very generic code like this, you generally have to specify all the constraints you use. But you could also give this function a simpler non-generic type such as Double -> Double -> String.

Haskell Type Error From Function Application to Function Composition

This question is related to this Function Composition VS Function Application which answered by antal s-z.
How you can get this ?
map has type (a -> b) -> [a] -> [b]
head has type [a] -> a
map head has type [[a]] -> [a]
Why the following code has type error for function composition ?
test :: [Char] -> Bool
test xs = not . null xs
getMiddleInitials :: [String] -> [Char]
getMiddleInitials middleNames = map head . filter (\mn -> not . null mn) middleNames
but this does not have type error
getFirstElements :: [[a]] -> [a]
getFirstElements = map head . filter (not . null)
Is it a must to write a point free function in order to utilize the function composition ?
I still not very understand the usage of function composition.
Please help.
Thanks.
That's just because function application x y has higher precedence than composition x . y
test :: [Char] -> Bool
test xs = (not . null) xs
-- # ^ ^
getMiddleInitials :: [String] -> [Char]
getMiddleInitials middleNames = (map head . filter (\mn -> (not . null) mn)) middleNames
-- # ^ ^ ^ ^
Your error here is actually really simple. If you remember the last part of my answer to your last question, the . operator has higher precedence than anything except for function application. Thus, consider your example of
test :: [Char] -> Bool
test xs = not . null xs
This is parsed as test xs = not . (null xs). Of course, null xs has type Bool, and you can't compose a boolean, and so you get a type error. Thus, you could make your examples work like so:
test :: [Char] -> Bool
test xs = (not . null) xs
getMiddleInitials :: [String] -> [Char]
getMiddleInitials middleNames =
(map head . filter (\mn -> (not . null) mn)) middleNames
Of course, writing it this way is unusual, but it would work fine.
And no, there are other uses of function composition besides point-free style. One example is to use function composition for some things (e.g. the argument to map or filter), but specify the rest. For instance, take this contrived example:
rejectMapping :: (a -> Bool) -> (a -> b) -> [a] -> [b]
rejectMapping p f = map f . filter (not . p)
This is partly point-free (not . p, for instance, and we left off the final argument), but partly point-full (the existence of p and f).

Using an element against an entire list in Haskell

I have an assignment and am currently caught in one section of what I'm trying to do. Without going in to specific detail here is the basic layout:
I'm given a data element, f, that holds four different types inside (each with their own purpose):
data F = F Float Int, Int
a function:
func :: F -> F-> Q
Which takes two data elements and (by simple calculations) returns a type that is now an updated version of one of the types in the first f.
I now have an entire list of these elements and need to run the given function using one data element and return the type's value (not the data element). My first analysis was to use a foldl function:
myfunc :: F -> [F] -> Q
myfunc y [] = func y y -- func deals with the same data element calls
myfunc y (x:xs) = foldl func y (x:xs)
however I keep getting the same error:
"Couldn't match expected type 'F' against inferred type 'Q'.
In the first argument of 'foldl', namely 'myfunc'
In the expression: foldl func y (x:xs)
I apologise for such an abstract analysis on my problem but could anyone give me an idea as to what I should do? Should I even use a fold function or is there recursion I'm not thinking about?
The type of foldl is
foldl :: (a -> b -> a) -> a -> [b] -> a
but the type of func is
-- # a -> b -> a
func :: F -> F -> Q
The type variable a cannot be simultaneously F and Q, thus the error.
If the Q can be converted to and from F, you could use
myfunc y xs = foldl (func . fromQ) (toQ y) xs
where
func . fromQ :: Q -> F -> Q
toQ y :: Q
xs :: [F]
so this satisfies all the type requirements, and will return the final Q.
maybe you need map?
map :: (f -> q) -> [f] -> [q]
it evaluates a function on each element in a list and gives a list of the results. I'm not sure why your function takes two Fs though, possibly to work with foldl?

Function application: Why is $ used here?

A while ago, I asked a question about $, and got useful answers -- in fact, I thought I understood how to use it.
It seems I was wrong :(
This example shows up in a tutorial:
instance Monad [] where
xs >>= f = concat . map f $ xs
I can't for the life of me see why $ was used there; ghci isn't helping me either, as even tests I do there seem to show equivalence with the version that would simply omit the $. Can someone clarify this for me?
The $ is used here because it has lower precedence than normal function application.
Another way to write this code is like so:
instance Monad [] where
xs >>= f = (concat . map f) xs
The idea here is to first construct a function (concat . map f) and then apply it to its argument (xs). As shown, this can also be done by simply putting parenthesis around the first part.
Note that omitting the $ in the original definition is not possible, it will result in a type error. This is because the function composition operator (the .) has a lower precedence than normal function application effectively turning the expression into:
instance Monad [] where
xs >>= f = concat . (map f xs)
Which doesn't make sense, because the second argument to the function composition operator isn't a function at all. Although the following definition does make sense:
instance Monad [] where
xs >>= f = concat (map f xs)
Incidentally, this is also the definition I would prefer, because it seems to me to be a lot clearer.
I'd like to explain why IMHO this is not the used style there:
instance Monad [] where
xs >>= f = concat (map f xs)
concat . map f is an example of so-called pointfree-style writing; where pointfree means "without the point of application". Remember that in maths, in the expression y=f(x), we say that f is applied on the point x. In most cases, you can actually do a final step, replacing:
f x = something $ x
with
f = something
like f = concat . map f, and this is actually pointfree style.
Which is clearer is arguable, but the pointfree style gives a different point of view which is also useful, so sometimes is used even when not exactly needed.
EDIT: I have replaced pointless with pointfree and fixed some examples, after the comment by Alasdair, whom I should thank.
The reason $ is used here is doe to the type signature of (.):
(.) :: (b -> c) -> (a -> c) -> a -> c
Here we have
map f :: [a] -> [[b]]
and
concat :: [[b]] -> [b]
So we end up with
concat . map f :: [a] -> [b]
and the type of (.) could be written as
(.) :: ([[b]] -> [b]) -> ([a] -> [[b]]) -> [a] -> [b]
If we were to use concat . map f xs, we'd see that
map f xs :: [[b]]
And so cannot be used with (.). (the type would have to be (.) :: (a -> b) -> a -> b