2

What does (n+1) mean? I understand both are recursive Haskell functions and are using pattern matching.

I don't understand how it will pattern match factorial (n+1) as well as the (n+1) on the RHS of factorial =.

And with the drop function why is it drop 0 xs = xs? And what about drop (n+1) [] = []?

--Example 1
factorial 0 = 1
factorial (n+1) = (n+1) * factorial n

--Example 2
drop :: Int -> [a] -> [a]
drop 0 xs = xs
drop (n+1) [] = []
drop (n+1) (_:xs) = drop n xs

By the way I get errors when compiling.

  • Code failed to compile
  • Parse error in pattern: n + 1

Update: Thanks for pointing me to the correct terminology. I found this n+k patterns. Since n+k patterns have been removed since 2010 I also found this question on how to enable this pattern.

Community
  • 1
  • 1
Jeff
  • 13,079
  • 23
  • 71
  • 102

3 Answers3

7

These are NPlusKPatterns, which were removed from the language in 2010, and are now only available with the mentioned language extension.

An n + k-pattern

drop (n+1) [] = []

binds n to the argument value minus one, provided that the argument value is >= 1. The pattern does not match arguments <= 0.

So if

drop :: Int -> [a] -> [a]
drop 0 xs = xs
drop (n+1) [] = []
drop (n+1) (_:xs) = drop n xs

is called with a negative Int argument, like

drop (-2) "foo"

no pattern matches, and you get an exception.

Generally, if you define (for a stupid example)

foo :: Int -> Int
foo (n+5) = 3*n
foo (n+2) = n
foo (n+1) = 2*n

if you call foo 7, the first pattern matches and n will be bound to 2, so foo 7 = 6. If you call foo 3, the first pattern doesn't match (3-5 = -2 < 0), but the second does, and that binds n to 3-2 = 1, hence foo 3 = 1. If you call foo 1, neither of the first two patterns matches, but the last does, and then n is bound to 1 - 1 = 0, so foo 1 = 0. Calling foo with an argument < 1 raises an exception.

And with drop function why is it drop 0 xs = xs? And what about drop (n+1) [] = []?

Well, drop 0 drops 0 elements from the front of the list, so it doesn't change the list argument at all. And you can't drop elements from an empty list, so drop (n+1) [] = [] is the only thing you can do except raising an error.

Daniel Fischer
  • 181,706
  • 17
  • 308
  • 431
  • Confused and so you are saying I don't need to learn this pattern as a newbie Haskeller? – Jeff Jun 26 '13 at 11:26
  • 6
    More or less. If the book/tutorial you learn from uses them (extensively), you need to (and will) learn them. But they have been removed from the language with a reason, and you won't see many `n+k`-patterns in production code. – Daniel Fischer Jun 26 '13 at 11:29
  • 2
    Confused = this is partly why they removed it. – MathematicalOrchid Jun 27 '13 at 19:55
6

This is a so called n+k pattern. The pattern (n+1) matches any positive integer and gives n the value of that integer minus one. So if you call drop 1 xs the value of n will be 0.

why is it drop 0 xs = xs

Because if you remove 0 elements from a list, you end up with the same list.

And what about drop (n+1) [] = []?

That says that if you remove any amount of items from the empty list, you end up with a list that's still empty. Other than failing with an error message, that's really the only sensible thing you can do in that case.

sepp2k
  • 363,768
  • 54
  • 674
  • 675
  • "It matches any positive integer and gives n the value of that integer minus one." now I am totally totally confused...!!! – Jeff Jun 26 '13 at 11:24
  • By "minus one" did you really mean "minus k"? – Jeff Jun 26 '13 at 11:27
  • 1
    @Jeff If you call `drop 1 xs` then `n` is 0 because `0+1` is `1`, so `drop 1 xs` matches `drop (0+1) xs`, which matches `drop (n+1) xs` for `n=0`. – sepp2k Jun 26 '13 at 11:27
  • What about (n+2)? Sorry still confused :_) – Jeff Jun 26 '13 at 11:28
  • 1
    @Jeff Sorry, yes, I was specifically about `n+1` in that sentence. Generally an `n+k` pattern matches a number greater than or equal to `k` and gives `n` the value of that integer minus `k`. – sepp2k Jun 26 '13 at 11:29
  • 2
    @Jeff No, there never were `n-k` patterns. Ugh, I just imagined there were, and sombody mixed `n+k` and `n-k` patterns. – Daniel Fischer Jun 26 '13 at 11:44
  • 1
    is k then strictly positive? (can one use `n+(-1)`?) – nlucaroni Jun 26 '13 at 18:08
3

The code you provided uses feature called NPlusKPatterns that is no longer part of standard haskell (Not in the haskell2010 standard), but it is possible to "import" it by putting the line {-# LANGUAGE NPlusKPatterns #-} at the top of the source file.

Lets look at an example of how to use it:

myFunction 0 = 0
myFunction (n+1) = n

This function is somewhat silly. If the input is 0 then the result is 0. For a positive input number m the result is m - 1, or said differently, for a positive input number n+1 the result is n. The function is undefined for negative numbers since the (n+1) pattern does not match negative numbers.

Now lets say I changed my function to

myFunction 0 = 0
myFunction (n+1) = (n+1)

Now the left side does some magic. It declares a variable n which is one minus the input. The right side on the other hand, adds back one to it with the (+) operator.

As for your questions about the drop function. drop 0 xs = xs means that dropping 0 elements from a list doesn't change the list. drop (n+1) [] = [] is simply that dropping any positive number of elements from an empty list is the empty list.

The definition of drop from the haskell2010 report is:

drop n xs     | n <= 0 =  xs
drop _ []              =  []
drop n (_:xs)          =  drop (n-1) xs

which behaves somewhat differently since it is defined for negative numbers.

HaskellElephant
  • 9,819
  • 4
  • 38
  • 67