Currying subtraction - haskell

If we want to map a function that increases every element of a range by 1, we could write
map (\x -> x + 1) [1..5]
but I guess most people would just go for
map (+1) [1..5]
instead. But this obviously doesn't work with (-1) since that's negative one.
So the first thing that came to mind was
map (+(-1)) [1..5]
which would make sense considering how subtraction is defined in the Prelude (x - y = x + negate y), but looks a bit odd to me. I then I came up with
map (flip (-) 1) [1..5]
This somehow looks better to me, but is maybe a bit too complicated.
Now I know this no big deal, but I'm wondering if I'm missing a more obvious way to write this? If not, which of the 2 ways would you prefer? I'm really just asking because often it's small details like this that make your code more idiomatic and hence pleasant for other developers who have to read it.
Solution
Now that I got a couple of answers, I think my personal favorite is
map (subtract 1) [1..5]
followed by
map pred [1..5]
mostly because the first one is really explicit and nobody needs to guess/look up what pred means (predecessor).

You can use the subtract function instead of - if you want to right-section subtraction:
map (subtract 1) [1..5]

Since - is both the infix subtract and the prefix negate, you can't use the (*x) (where * is an infix operator and x a value) syntax for -. Luckily Prelude comes with negate and subtract, which is \x -> -x and \x y -> y-x respectively, so that you may use those where you need to differentiate between the two.

After many years since this question was asked, in GHC 9 we now have
the LexicalNegation extension which allows the section (- 1), as long we use whitespace to separate the minus sign from the number.
Indeed, after enabling the extension, we have:
> map (subtract 1) [1..5] -- still works, of course
[0, 1, 2, 3, 4]
> map (- 1) [1..5] -- with whitespace
[0, 1, 2, 3, 4] -- (- 1) is now a section
> map (-1) [1..5] -- no whitespace
*error* -- (-1) is now a negative literal

I think map (\x -> x - 1) [1..5] transmits the programmer's intention better, since there's no doubt about what is being subtracted from what. I also find your first solution, map (+(-1)) [1..5], easy to read too.

I don't like subtract because it's confusingly backwards. I'd suggest
minus :: Num n => n -> n -> n
minus = (-)
infixl 6 `minus`
Then you can write
map (`minus` 1) [1..5]

Related

Haskell: Purpose of the flip function?

I am a bit surprised that this was not asked before. Maybe it is a stupid question.
I know that flip is changing the order of two arguments.
Example:
(-) 5 3
= 5 - 3
= 2
flip (-) 5 3
= 3 - 5
= -2
But why would I need such a function? Why not just change the inputs manually?
Why not just write:
(-) 3 5
= 3 - 5
= -2
One is unlikely to ever use the flip function on a function that is immediately applied to two or more arguments, but flip can be useful in two situations:
If the function is passed higher-order to a different function, one cannot simply reverse the arguments at the call site, since the call site is in another function! For example, these two expressions produce very different results:
ghci> foldl (-) 0 [1, 2, 3, 4]
-10
ghci> foldl (flip (-)) 0 [1, 2, 3, 4]
2
In this case, we cannot swap the arguments of (-) because we do not apply (-) directly; foldl applies it for us. So we can use flip (-) instead of writing out the whole lambda \x y -> y - x.
Additionally, it can be useful to use flip to partially apply a function to its second argument. For example, we could use flip to write a function that builds an infinite list using a builder function that is provided the element’s index in the list:
buildList :: (Integer -> a) -> [a]
buildList = flip map [0..]
ghci> take 10 (buildList (\x -> x * x))
[0,1,4,9,16,25,36,49,64,81]
Perhaps more frequently, this is used when we want to partially apply the second argument of a function that will be used higher-order, like in the first example:
ghci> map (flip map [1, 2, 3]) [(+ 1), (* 2)]
[[2,3,4],[2,4,6]]
Sometimes, instead of using flip in a case like this, people will use infix syntax instead, since operator sections have the unique property that they can supply the first or second argument to a function. Therefore, writing (`f` x) is equivalent to writing flip f x. Personally, I think writing flip directly is usually easier to read, but that’s a matter of taste.
One very useful example of flip usage is sorting in descending order. You can see how it works in ghci:
ghci> import Data.List
ghci> :t sortBy
sortBy :: (a -> a -> Ordering) -> [a] -> [a]
ghci> :t compare
compare :: Ord a => a -> a -> Ordering
ghci> sortBy compare [2,1,3]
[1,2,3]
ghci> sortBy (flip compare) [2,1,3]
[3,2,1]
Sometimes you'll want to use a function by supplying the second parameter but take it's first parameter from somewhere else. For example:
map (flip (-) 5) [1..5]
Though this can also be written as:
map (\x -> x - 5) [1..5]
Another use case is when the second argument is long:
flip (-) 5 $
if odd x
then x + 1
else x
But you can always use a let expression to name the first parameter computation and then not use flip.

foldr - further explanation and example with a map function

I've looked at different folds and folding in general as well as a few others and they explain it fairly well.
I'm still having trouble on how it would work in this case.
length :: [t] -> Int
length list = foldr (+) 0 (map (\x ->1) list)
Could someone go through that step by step and try to explain that to me.
And also how would foldl work as well.
(map (\x ->1) list) takes the list and turns it into a list of 1 values:
(map (\x ->1) ["a", "b", "c"]) == [1, 1, 1]
Now, if you substitute that in the original foldr, it looks like this:
foldr (+) 0 [1, 1, 1]
The starting point is 0 and the aggregation function is (+). As it steps through each element in the list, you are basically adding up all the 1 values, and that's how you end up returning the length.
foldr starts from the right and works back to the head of the list. foldl starts from the left and works through the list. Because the aggregation function is (+) :: Num a => a -> a -> a, the ordering of the left and right arguments in (+) is logically inconsequential (with the caveat that foldl has stack overflow problems with large lists because of lazy evaluation)

How to filter all multiples of a certain number out of a list in Haskell using filter

I know I can make a function to do this but can I use the filter function from the prelude. I can easily filter all numbers larger than 3 for instance from a list using
filter (>3) [list]
But I want something like
filter (not (.. `mod` 4 == 0)) [list]
that filters out all multiples of four. I put the .. here because I dont know what goes there. Is there any way I can do this using the filter function or should I make my own function to do this? Thanks in advance
You were almost there:
filter (\n -> not (n `mod` 4 == 0)) [list]
The \n is read "lambda n", and introduces an anonymous function. Namely, the function which, given n tests if it is not a multiple of 4.
Otherwise, you can use the "pointfree" style, in which you compose several functions:
filter (not . (== 0) . (`mod` 4)) [list]
The function reads as: take the input, reduce it modulo 4, then test if the result is equal to 0, and finally negate the result of such test.
Note that you can also use /= 0 instead of == 0 and negation.
As an aside: the latest versions of ghc have an extension called TypeHoles, that can sometimes help with those "I put the .. here because I dont know what goes there" types of situations.
It is enabled by default in ghci. If you leave _ in place on an expression in your code, ghc will try to infer what type a thing in the _ could have.
# :t filter _ [1,2,3,4]::[Int]
<interactive>:1:8:
Found hole `_' with type: Int -> Bool
In the first argument of `filter', namely `_'
In the expression: filter _ [1, 2, 3, ....] :: [Int]
It becomes more helpful as the types become more complicated.
Use a lambda expression:
filter (\x -> x `mod` 4 /= 0) list
Or if you're adventurous use point free style:
filter ((/= 0) . (`mod` 4)) list
(I assume the [] around list was a mistake, you probably don't want a list of just one element called list.)

Apply a constant subtraction using map in Haskell

I simply want to substract 1 from every list element in [1,2,3,4] like
map (-1) [1,2,3,4] -- does not work
map ((-)1) [1,2,3,4] -- gives [0,-1,-2,-3] which is "-listvalue" + 1
map (\x = x - 1) [1,2,3,4] -- what I want but so verbose
map (+ (-1)) [1,2,3,4] -- well :)
map (flip (-) 1) [1,2,3,4] -- I heard of flip before
(map . flip (-)) 1 [1,2,3,4] -- Kinda nice mapped substration composing thingy
map pred [1,2,3,4] -- OK cheated and won't help with -2
Do I miss a form which would be "correct" and / or what Mr. Haskell use?
You can use the subtract function instead
map (subtract 1) [1,2,3,4]
You've run into a minor wart of Haskell's design. The expression (-1) could in principle be interpreted in two ways:
A section that partially applies the subtraction operator to its second argument.
The application of the unary sign operator to the number 1.
Haskell goes with #2. To make up for this the subtract function is provided to cover case #1.

What are some better ways to write [(-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1)] in Haskell?

I've run in to a few situations where I need the list:
[(-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1)] -- no (0,0)
Note that there is no (0,0) in the list. I use the (dx,dy) tuples to search up, down, left, right and diagonally from a coordinate.
Every time I write it I feel like there should be a more concise, and/or easier to read way to define it. I'm relatively new to Haskell and I figure somewhere in the bag of Applicative/Functor/Monad tricks there should be a neat way to do this.
I've tried:
[(-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1)]
Sometimes it's better just to write it out, but I don't think this is one of those times. It's not obvious with a glance that (0,0) isn't included, and you have to read it a bit to notice the pattern.
map (\[a,b] -> (a,b)) $ delete [0,0] $ sequence $ replicate 2 [-1,0,1]
I like the one above because I get to put the "2" in there which is a nice explicit way to say "We're doing the same sort of thing twice", but I can't accept the map in front with the big unsafe lambda and 2 names.
[(dx,dy) | let a = [-1,0,1], dx <- a, dy <- a, (dx,dy) /= (0, 0)]
This one has too many names in it, but uses the list comprehension exactly as it is designed. It might be easier to read for somebody who really likes list comprehensions, but I don't like all the names.
let x = [-1,0,1] in delete (0,0) $ (,) <$> x <*> x
That one looks prettier imo, but I don't have that "2" in there, and I have a name. This is my favorite so far, but it doesn't feel perfect.
I think if I understood how to write this better I might have a deeper understanding of Functors/Monads or the like. I've read about them quite a bit, and I've heard a bunch of words like fmap/mconcat/etc, but I don't know which one to grab for in this situation.
Actually, I think it's indeed best to write it out explicitly in this case. Just align it reasonably, and no questions stay open whatsoever:
neighbours = [ (-1,-1), (-1,0), (-1,1)
, ( 0,-1), ( 0,1)
, ( 1,-1), ( 1,0), ( 1,1) ]
There's no way any alternative could be more self-explanatory than this.
Of course, there are more concise alternatives. Being a physics guy, I'd tend to
[ (round $ - sin φ, round $ - cos φ) | φ <- [pi/4, pi/2 .. 2*pi] ]
which is of course more expensive to compute, but that doesn't matter if you only define this list at one place and re-use it from all over you program. The order is different here, not sure if that matters.
Why not just use a list comprehension? They can have boolean guards in them, so excluding (0,0) is pretty simple:
[(i,j) | i <- [-1..1], j <- [-1..1], (i,j) /= (0,0)]
Note that as a Haskell newb myself, there is likely a more compact/efficient way to write that guard expression. Nonetheless, this gets the job done.
Prelude Data.Ix Data.List> delete (0,0) (range ((-1,-1),(1,1)))
[(-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1)]
Here's a concise version using stuff from Control.Applicative:
delete (0, 0) $ (,) <$> [-1..1] <*> [-1..1]
Personally, I think this looks much better using &, which is just $ flipped.
(,) <$> [-1..1] <*> [-1..1] & delete (0, 0)
You could also use liftA2 instead of <$> and <*>:
liftA2 (,) [-1..1] [-1..1] & delete (0, 0)
It's defined in the lens library, among other place, but you can define it yourself:
infixl 1 &
x & f = f x
All that said, I still prefer the version with the list comprehension or even just the literal list with good indentation.
liftA2 zip (!!0) (!!1) . transpose . tail . replicateM 2 $ [0,1,-1]
(Not that I recommend this.)
Prelude> let sqrt' n | n == 0 = [0] | otherwise = [sqrt n, negate (sqrt n)]
Prelude> [(x,y) | x <- [-1..1]
, y <- sqrt' (1 - x^2) ++ (if x==0 then [] else sqrt' (2 - x^2))]
For easier to read you could try:
left = (-1,0)
right = (1,0)
up = (0,1)
down = (0,-1)
--etc
directions = [left,right,up,down]
These are really vectors, so you might want to consider using a vector library if it makes sense in your app, or create your own custom vector operations:
import Data.Vect
vecUp = Vec2 0,1
vecDown = Vec2 0,(-1)
--etc.
goUp10 = 10 *& vecUp -- '*&' is the scalar multiply operator

Resources