I tried the $ operator and came to a weird point where I don't understand what is happening.
f = double $ 3+4
but this does not
f xs = xs !! $ length xs - 1
Can the operator $ only appear after function names and not after operators?
If so is there a way to write the following function without the parenthesis
f xs = xs !! (length xs - 1)
You can't have two operators next to each other, it's invalid syntax. This holds true for all operators. So xs !! $ length xs - 1 just will not work. There isn't really a good way to get rid of the parens in that statement without resorting to some tricks that aren't worth it and make the code less readable.
The $ operator does not have to appear after function names, though, you can do
> let add x y = x + y
> add 1 $ add 2 $ add 3 4
Haskell infix notation is problematic, avoid it like this
f xs = (!!) xs $ length xs - 1
The brackets turn an infix operator into a prefix function.
Related
The code is
prime (x:xs) = x:prime (filter (\y -> y `mod` x /=0) xs)
If I change it to
prime (x:xs) = x:prime $ filter (\y -> y `mod` x /=0) xs
There is a pattern matching error.
If I try to reproduce the error, it seems like GHC understands it like so:
(x : prime) $ filter (\y -> y `mod` x /= 0) xs
But you want it like that:
x : (prime $ filter (\y -> y `mod` x /= 0) xs)
So you just have to use bracket notation, I think.
First of all, it's a misconception that $ is a syntactic replacement for () — $ is a regular operator (which itself is a function that is simply infix by default); it's just the precedence rules that make $ convenient in many cases — but there's no syntactic magic behind it.
Now, ignoring the irrelevant bits, let's just concentrate on the part of the code that's causing the error:
x : prime (foo bar)
is the same as
x : (prime (foo bar))
because the : on the left has a lower precedence than the function application on the right.
However
x : prime $ foo bar
is the same as
(x : prime) $ (foo bar)
which is the same as
(x : prime) (foo bar)
because the : on the left has a higher precedence than the $ on the right.
So the error comes from the fact that you're trying to apply the result of the expression x : prime to the argument foo bar as if x : prime were a function, but it's not, hence the type error.
Solution? Either throw in some parentheses, or even better, don't use the $ at all in this case.
When you write:
x : prime $ filter foo xs
It is interpreted as
(x : prime) $ filter foo xs
due to (:) having a higher precedence than ($). See the fixity declarations section of this report for more.
It fails because a list of functions ((x:prime)) is not a function, and cannot be used as such.
If you want to make the function prettier, try this:
prime (x:xs) = x : prime (filter ((/= 0) . (`mod` x)) xs)
Others have already explained the problem. Here is one solution:
prime (x:xs) = (x:) $ prime $ filter (\y -> y `mod` x /=0) xs
That is, you can use an operator section to express the application of : to x and then apply the result as you like.
I just started using Haskell and wanted to write a function that, given a list, returns a list in which every 2nd element has been doubled.
So far I've come up with this:
double_2nd :: [Int] -> [Int]
double_2nd [] = []
double_2nd (x:xs) = x : (2 * head xs) : double_2nd (tail xs)
Which works but I was wondering how you guys would write that function. Is there a more common/better way or does this look about right?
That's not bad, modulo the fixes suggested. Once you get more familiar with the base library you'll likely avoid explicit recursion in favor of some higher level functions, for example, you could create a list of functions where every other one is *2 and apply (zip) that list of functions to your list of numbers:
double = zipWith ($) (cycle [id,(*2)])
You can avoid "empty list" exceptions with some smart pattern matching.
double2nd (x:y:xs) = x : 2 * y : double2nd xs
double2nd a = a
this is simply syntax sugar for the following
double2nd xss = case xss of
x:y:xs -> x : 2 * y : double2nd xs
a -> a
the pattern matching is done in order, so xs will be matched against the pattern x:y:xs first. Then if that fails, the catch-all pattern a will succeed.
A little bit of necromancy, but I think that this method worked out very well for me and want to share:
double2nd n = zipWith (*) n (cycle [1,2])
zipWith takes a function and then applies that function across matching items in two lists (first item to first item, second item to second item, etc). The function is multiplication, and the zipped list is an endless cycle of 1s and 2s. zipWith (and all the zip variants) stops at the end of the shorter list.
Try it on an odd-length list:
Prelude> double_2nd [1]
[1,*** Exception: Prelude.head: empty list
And you can see the problem with your code. The 'head' and 'tail' are never a good idea.
For odd-lists or double_2nd [x] you can always add
double_2nd (x:xs) | length xs == 0 = [x]
| otherwise = x : (2 * head xs) : double_2nd (tail xs)
Thanks.
Here's a foldr-based solution.
bar :: Num a => [a] -> [a]
bar xs = foldr (\ x r f g -> f x (r g f))
(\ _ _ -> [])
xs
(:)
((:) . (*2))
Testing:
> bar [1..9]
[1,4,3,8,5,12,7,16,9]
I need to get the nth element of a list but without using the !! operator. I am extremely new to haskell so I'd appreciate if you can answer in more detail and not just one line of code. This is what I'm trying at the moment:
nthel:: Int -> [Int] -> Int
nthel n xs = 0
let xsxs = take n xs
nthel n xs = last xsxs
But I get: parse error (possibly incorrect indentation)
There's a lot that's a bit off here,
nthel :: Int -> [Int] -> Int
is technically correct, really we want
nthel :: Int -> [a] -> a
So we can use this on lists of anything (Optional)
nthel n xs = 0
What you just said is "No matter what you give to nthel return 0". which is clearly wrong.
let xsxs = ...
This is just not legal haskell. let ... in ... is an expression, it can't be used toplevel.
From there I'm not really sure what that's supposed to do.
Maybe this will help put you on the right track
nthelem n [] = <???> -- error case, empty list
nthelem 0 xs = head xs
nthelem n xs = <???> -- recursive case
Try filling in the <???> with your best guess and I'm happy to help from there.
Alternatively you can use Haskell's "pattern matching" syntax. I explain how you can do this with lists here.
That changes our above to
nthelem n [] = <???> -- error case, empty list
nthelem 0 (x:xs) = x --bind x to the first element, xs to the rest of the list
nthelem n (x:xs) = <???> -- recursive case
Doing this is handy since it negates the need to use explicit head and tails.
I think you meant this:
nthel n xs = last xsxs
where xsxs = take n xs
... which you can simplify as:
nthel n xs = last (take n xs)
I think you should avoid using last whenever possible - lists are made to be used from the "front end", not from the back. What you want is to get rid of the first n elements, and then get the head of the remaining list (of course you get an error if the rest is empty). You can express this quite directly as:
nthel n xs = head (drop n xs)
Or shorter:
nthel n = head . drop n
Or slightly crazy:
nthel = (head .) . drop
As you know list aren't naturally indexed, but it can be overcome using a common tips.
Try into ghci, zip [0..] "hello", What's about zip [0,1,2] "hello" or zip [0..10] "hello" ?
Starting from this observation, we can now easily obtain a way to index our list.
Moreover is a good illustration of the use of laziness, a good hint for your learning process.
Then based on this and using pattern matching we can provide an efficient algorithm.
Management of bounding cases (empty list, negative index).
Replace the list by an indexed version using zipper.
Call an helper function design to process recursively our indexed list.
Now for the helper function, the list can't be empty then we can pattern match naively, and,
if our index is equal to n we have a winner
else, if our next element is empty it's over
else, call the helper function with the next element.
Additional note, as our function can fail (empty list ...) it could be a good thing to wrap our result using Maybe type.
Putting this all together we end with.
nth :: Int -> [a] -> Maybe a
nth n xs
| null xs || n < 0 = Nothing
| otherwise = helper n zs
where
zs = zip [0..] xs
helper n ((i,c):zs)
| i == n = Just c
| null zs = Nothing
| otherwise = helper n zs
I'm currently at 6th chapter of Learn you a Haskell... Just recently started working my way on 99 questions.
The 3rd problem is to find the K'th element of a list. I've implemented it using take and zip.
The problem I have is understanding the alternate solution offered:
elementAt''' xs n = head $ foldr ($) xs
$ replicate (n - 1) tail
I'm "almost there" but I don't quite get it. I know the definition of the $ but.. Can you please explain to me the order of the execution of the above code. Also, is this often used as a solution to various problems, is this idiomatic or just... acrobatic ?
If you expand the definition of foldr
foldr f z (x1:x2:x3:...:[]) = x1 `f` x2 `f` x3 `f`... `f` z
you see that elementAt''' becomes
elementAt''' xs n = head (tail $ tail $ ... $ tail $ xs)
(note: it should be replicate n tail instead of replicate (n-1) tail if indexing is 0-based).
So you apply tail to xs the appropriate number of times, which has the same result as drop (n-1) xs if xs is long enough, but raises an error if it's too short, and take the head of the resulting list (if xs is too short, that latter would also raise an error with drop (n-1)).
What it does is thus
discard the first element of the list
discard the first element of the resulting list (n-1 times altogether)
take the head of the resulting list
Also, is this often used as a solution to various problems, is this idiomatic or just... acrobatic
In this case, just acrobatic. The foldr has to expand the full application before it can work back to the front taking the tails, thus it's less efficient than the straightforward traversal.
Break it down into the two major steps. First, the function replicates tail
(n-1) times. So you end up with something like
elementAt''' xs n = head $ foldr ($) xs [tail, tail, tail, ..., tail]
Now, the definition of foldr on a list expands to something like this
foldr f x [y1, y2, y3, ..., yn] = (y1 `f` (y1 `f` (... (yn `f` x))) ...)
So, that fold will expand to (replace f with $ and all the ys with tail)
foldr ($) xs [tail, tail, tail, ..., tail]
= (tail $ (tail $ (tail $ ... (tail xs))) ... )
{- Since $ is right associative anyway -}
= tail $ tail $ tail $ tail $ ... $ tail xs
where there are (n-1) calls to tail composed together. After taking n-1
tails, it just extracts the first element of the remaining list and gives that
back.
Another way to write it that makes the composition more explicit (in my opinion) would
be like this
elementAt n = head . (foldr (.) id $ replicate (n-1) tail)
when you split a list using x:xs syntax why is it wrapped in a parentheses? what is the significance of the parentheses? why not [x:xs] or just x:xs?
The cons cell doesn't have to be parenthesized in every context, but in most contexts it is because
Function application binds tighter than any infix operator.
Burn this into your brain in letters of fire.
Example:
length [] = 0
length (x:xs) = 1 + length xs
If parentheses were omitted the compiler would think you had an argument x followed by an ill-placed infix operator, and it would complain bitterly. On the other hand this is OK
length l = case l of [] -> 0
x:xs -> 1 + length xs
In this case neither x nor xs can possibly be construed as part of a function application so no parentheses are needed.
Note that the same wonderful rule function application binds tighter than any infix operator is what allows us to write length xs in 1 + length xs without any parentheses. The infix rule giveth and the infix rule taketh away.
You're simply using the cons operator :, which has low precedence. Parentheses are needed so that things stay right.
And you don't use [x:xs], because that would match a list whose only element is a list with head x and tail xs.
I don't know exact answer, but I guess that is due to what can be matched in patterns. Only constructors can be matched. Constructors can be of single word or composite. Look at the next code:
data Foo = Bar | Baz Int
f :: Foo -> Int
f Bar = 1
f (Baz x) = x - 1
Single word constructors match as is. But composite constructors must be surrounded with parens in order to avoid ambiguity. If we skip parens it looks like matching against two independent arguments:
f Baz x = x - 1
So, as (:) is composite it must be in parens. Skipping parens for Bar is a kind of syntactic sugar.
UPDATE: I realized that (as sykora noted) it is a consequence of operator precedence. It clarifies my assumptions. Function application (which is just space between function and argument) has highest precedence. Others including (:) have lower precedence. So f x:xs is to be interpreted as ((:) (f x)) xs that is presumably not what we need. While f (x:xs) is interpreted as f applied to x:xs which is in turn (:) applied to x and xs.
It's to do with parsing.
Remember, the colon : is just a constructor that's written with operator syntax. So a function like
foo [] = 0
foo (x:xs) = x + foo xs
could also be written as
foo [] = 0
foo ((:) x xs) = x + foo xs
If you drop the parenthesis in that last line, it becomes very hard to parse!
: is a data constructor, like any other pattern match, but written infix. The parentheses are purely there because of infix precedence; they're actually not required and can be safely omitted when precedence rules allow. For instance:
> let (_, a:_) = (1, [2, 3, 4]) in a
2
> let a:_ = "xyzzy"
'x'
> case [1, 2, 3] of; a:b -> a; otherwise -> 0;
1
Interestingly, that doesn't seem to work in the head of a lambda. Not sure why.
As always, the "juxtaposition" operator binds tighter than anything else, so more often than not the delimiters are necessary, but they're not actually part of the pattern match--otherwise you wouldn't be able to use patterns like (x:y:zs) instead of (x:(y:zs)).