map 2 function combination fails: syntax error? - function

I just know in Haskell "." could be used to combine functions, so I tried:
Prelude> map (++" world")["hello","abc"]
["hello world","abc world"]
Prelude> map (++" world". ++"xyz")["hello","abc"]
<interactive>:3:18: parse error on input `++'
Why I cannot do this? I tried named function, it's OK:
Prelude> map (head.tail)["hello","abc"]
"eb"
So how to correct my case? Thanks.

The name for the thing you are doing when you say (++ "world") is that you are using what is called a "right section" of a "partially applied infix operator":
https://wiki.haskell.org/Section_of_an_infix_operator
What that means for (++ "world") is that the left hand side will be the parameter for the generated function, which will pre-fill the right hand side with "world".
So it's not just a use of parentheses for precedence... it's a special syntax. When you omit the parentheses on the second ++, that means you aren't invoking the syntax there. It tries to interpret it as normal infix.
If you want to compose two functions of this type inlined like this, you have them each in parentheses:
Prelude> map ((++" world") . (++"xyz"))["hello","abc"]
["helloxyz world","abcxyz world"]
Note the effects on the result if you merely convert the ++ operators to prefix, with the non-partially-applied syntax:
Prelude> map ((++) " world" . (++) "xyz")["hello","abc"]
[" worldxyzhello"," worldxyzabc"]
There you don't have to group them, but now you are providing the first argument instead. Your list's data winds up at the end of the output. This would be the same as if you used the infix partial application syntax with left sections:
Prelude> map ((" world" ++) . ("xyz" ++))["hello","abc"]
[" worldxyzhello"," worldxyzabc"]
FYI: if you want the composition to be in the reverse order (world first, then xyz) you could use >>> from Control.Arrow
Prelude> import Control.Arrow
Prelude Control.Arrow> map ((++" world") >>> (++"xyz")["hello","abc"]
["hello worldxyz","abc worldxyz"]

++ is an infix operator, and the rules of how you can use it are different than that of normal functions.
You can use it sandwiched between two values, like this
x ++ y
or convert it to a normal function using parenthesis
(++) x y --same as above
There are two ways to partially apply values to an infix operator
(x ++) --same as \y -> x ++ y
(++ y) --same as \x -> x ++ y
Both of these require the outer parentheses, else Haskell would try to parse the expression as the normal infix case
++ x . ++ y -- will confuse the parser
but
(++ x) . (++ y)
will work

Infix operators like parentheses.
Prelude> map ((++ " world") . (++ "xyz")) ["hello", "abc"]

Related

Confusion with function composition

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])

Rewriting an uncurried function haskell

I've been learning about uncurrying and applying $ in functions in haskell but I'm still having issues converting an uncurried function to something less mysterious.
The function I'm given is
apple = map $ uncurry $ flip ($)
and I realize that this takes a list of tuples and applies to corresponding function in the tuple to the variable inside. So I'm trying to rewrite it as
apple ls = foldr function _ ls
where function (a,b) c = (uncurry b) (a,c)
I get the error for _ as a parse error and I have no idea which starting point to use. I need to make this polymorphic and I'm realizing that this most likely will not be the way to make it less mysterious. Any ideas? They'd be greatly appreciated
Apple has the type
apple :: [(a, a->b)] -> [b]
We could rewrite it as
apple ls = map (\(a, f) -> f a) ls
So writing this with foldr is very doable,
apple ls = foldr (\(a, f) rest -> f a : rest) [] ls
Or, we can rewrite this to pointfree
apple = foldr ( (:) . (uncurry . flip $ ($)) ) []
The reason for the parse error is that _ is the special syntax for "variables I don't care about". This let's you write things like
foo _ _ _ _ a = a
And not get an error about repeated variables. Basically we just filled in _ with the starting empty list and fixed function so that it appends to c rather than trying to apply it to a.
If I wanted to write this in the clearest way possible, then the original
apple = map . uncurry . flip $ ($)
Is quite nice.
The key for understanding is removing complexity.
Thus I would suggest you deal with a single tuple first. Write the following function:
tapp :: (a, a ->b) -> b
in terms of ($) and flip and uncurry.
(To make it even easier, you could first do it for a tuple (a -> b, a) first).
Next, make clear to yourself how map works: If you have a function f :: (a -> b), then map f will be a function [a] -> [b]. Hence map tapp does what you want.
You can now replace tapp in map (tapp) by it's definition (this are the benefits of referential transparency).
And this should take you back to your original expression. More or less so, because, for example:
f $ g h
can be written
f (g h)
or
(f . g) h

Sort a list into tuples

I’m new to Haskell and am trying to sort a list of tuples using their first element, using the sort function. So if I had ["a", "b", "a", "c", "c"] I would get something like [(1,"b"), (2,"a"), (2,"c")] (in alphabetical order in the event of the same number).
How would I go about doing this? I am totally lost at the moment… I am still trying to get into the ‘Haskell way of thinking’.
import Data.List (sort, group)
import Control.Arrow ((&&&))
answer :: Eq a => [a] -> [(Int, a)]
answer = sort . map (length &&& head) . group . sort
But as you're a beginner, it's perhaps a bit much to tell you about &&&, so I'll rewrite it like this:
import Data.List (sort, group)
answer :: Eq a => [a] -> [(Int, a)]
answer = sort . map f . group . sort
where f xs # (x:_) = (length xs, x)
You'll note I'm calling sort twice. This is intentional.
The final sort (the one on the left) sorts the output list of tuples, and it just so happens that it sorts in ascending order of the first element of the tuple, breaking ties by sorting on the second element of the tuple.
The initial sort (the one on the right) sorts the input list, because of what group does: it groups adjacent equal elements into a sublist. (Incidentally, these sublists are guaranteed never to be empty --- otherwise it wouldn't be safe to use head or ignore the empty list option in the pattern match.)
The map f then turns these lists (e.g. ["a", "a"]) into what we're interested in: the number of times these elements occur, and a single representative of these elements (e.g. (2, "a")).
The idiom here is that we're using a pipeline: our input goes into a function, the output of that function goes into another function, and so on until the function at the end of the pipeline produces output that we present as our own output. Note that this only works because each function takes only a single argument (map takes two arguments, f is the first of those arguments, so map f takes one argument).
As a consequence of this, answer is a function even though its argument doesn't explicitly appear. This is point-free style.
In non point-free style, it would look like
answer xs = sort . map f . group . sort $ xs
where f xs # (x:_) = (length xs, x)
or
answer xs = sort $ map f $ group $ sort xs
where f xs # (x:_) = (length xs, x)
or
answer xs = sort (map f (group (sort xs)))
where f xs # (x:_) = (length xs, x)
It is a good idea to use point-free style when it makes your code clearer.
If you like, you can use the <<< operator (from Control.Arrow again, sorry) to make the dataflow direction superficially more explicit:
import Data.List (sort, group)
import Control.Arrow ((<<<))
answer :: Eq a => [a] -> [(Int, a)]
answer = sort <<< map f <<< group <<< sort
where f xs # (x:_) = (length xs, x)
Some people think that this is the wrong way round and want the functions that "happen" first to be on the left. These people can use >>> (also from Control.Arrow), which is exactly the same as <<< except its arguments are flipped round:
import Data.List (sort, group)
import Control.Arrow ((>>>))
answer :: Eq a => [a] -> [(Int, a)]
answer = sort >>> group >>> map f >>> sort
where f xs # (x:_) = (length xs, x)

How to make a Clojure function take a variable number of parameters?

I'm learning Clojure and I'm trying to define a function that take a variable number of parameters (a variadic function) and sum them up (yep, just like the + procedure). However, I don´t know how to implement such function
Everything I can do is:
(defn sum [n1, n2] (+ n1 n2))
Of course this function takes two parameteres and two parameters only. Please teach me how to make it accept (and process) an undefined number of parameters.
In general, non-commutative case you can use apply:
(defn sum [& args] (apply + args))
Since addition is commutative, something like this should work too:
(defn sum [& args] (reduce + args))
& causes args to be bound to the remainder of the argument list (in this case the whole list, as there's nothing to the left of &).
Obviously defining sum like that doesn't make sense, since instead of:
(sum a b c d e ...)
you can just write:
(+ a b c d e ....)
Yehoanathan mentions arity overloading but does not provide a direct example. Here's what he's talking about:
(defn special-sum
([] (+ 10 10))
([x] (+ 10 x))
([x y] (+ x y)))
(special-sum) => 20
(special-sum 50) => 60
(special-sum 50 25) => 75
(defn my-sum
([] 0) ; no parameter
([x] x) ; one parameter
([x y] (+ x y)) ; two parameters
([x y & more] ; more than two parameters
(reduce + (my-sum x y) more))
)
defn is a macro that makes defining functions a little simpler.
Clojure supports arity overloading in a single function object,
self-reference, and variable-arity functions using &
From http://clojure.org/functional_programming
(defn sum [& args]
(print "sum of" args ":" (apply + args)))
This takes any number of arguments and add them up.

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