You can't have the c+1
on the left side of a definition. Since you're just summing, it doesn't matter if you count up from 0 to c
or count down from c
to 0, so you could instead do
my_sum f a b 0 = f a b 0
my_sum f a b c = f a b c + my_sum f a b (c - 1)
Then you could use it as
> let g x y z = x + y + z
> my_sum g 0 0 10
55
Some more detail on why your code failed to compile: Whenever you have a pattern on the left side of a definition, such as
fib 0 = 1
fib 1 = 1
fib n = fib (n - 1) + fib (n - 2)
You can only match on constructors, names (like n
or c
), and literals (which are essentially constructors for the basic types). The function +
is not a constructor, it is a function belonging to the Num
typeclass, so therefore you can not pattern match on it. You may be confused from seeing list pattern matching before because it uses an operator:
myListSum [] = 0
myListSum (x:xs) = x + myListSum xs
but in fact, :
is the Cons
constructor for lists, and []
is the empty list constructor. You can think of the list type defined as
data [a] = [] | a : [a]
Or, if you were to replace all the symbols with words
data List a = Empty | Cons a (List a)
although its a bit different in reality since there's more that goes into defining lists, but that's the basic idea. This means that a pattern like
f [] = ...
f (x:xs) = ...
Is equivalent to
f Empty = ...
f (Cons x xs) = ...
just with more convenient syntax.
However, Int
can be though of as a very large ADT defined as
data Int = -2147483648 | -2147483647 | ... | -1 | 0 | 1 | ... | 2147483646 | 2147483647
where each number itself is a different constructor. Then you can match on any individual number, but not anything like (x + 1)
or (x * 2)
, because +
and *
are not constructors, just regular functions. (Note: Int
is not actually defined this way because that would be really inefficient, it's defined at a more primitive level)