rnso
rnso

Reputation: 24535

Runtime error - Non-exhaustive patterns in function

I want to write a function which prints out a list of numbers from 1 to n: [1,2,...n], I know it can be done by [1..n] but I want to make my own function:

addtimes n = addtimes_ [] n
addtimes_ [lst] a =
    if a < 1 
    then [lst]
    else  addtimes_ [a:lst] (a-1)
main = 
    print $ addtimes 10

Though above code compiles and runs, it gives following runtime error:

testing: testing.hs:(3,1)-(6,37): Non-exhaustive patterns in function addtimes_

Where is the problem and how can it be solved?

Upvotes: 1

Views: 90

Answers (2)

Robin Zigmond
Robin Zigmond

Reputation: 18249

See the following, with corrected syntax (and type signatures added, seriously these are essential for both code documentation and for better error messages):

addtimes :: (Num a, Ord a) => a -> [a]
addtimes n = addtimes_ [] n

addtimes_ :: (Num a, Ord a) => [a] -> a -> [a]
addtimes_ lst a =
    if a < 1 
    then lst
    else  addtimes_ (a:lst) (a-1)

main :: IO ()
main = 
    print $ addtimes 10

As well as referring to [lst] (a singleton list containing the one element lst) instead of lst (which can refer to anything, which in the context of your function must be a list, but can be of any length), you had put [a:lst] (again a singleton list, this time containing a list) instead of (a:lst), a list made up of first element a appended to the front of lst. (The parentheses are not needed for any syntactic reason, but are usually needed in practice, as in the above code, because of operator precedence: addtimes_ a:list (a-1) would be parsed as (addtimes_ a):(list (a-1)), which definitely isn't what you mean.

Upvotes: 5

developer_hatch
developer_hatch

Reputation: 16224

Edit:

To achieve what you want, now I understand your goal reading your

addtimes :: Int -> [Int]
addtimes 0       = []
addtimes n       = if n > 0
                   then addtimes_ 1 n
                   else error "Doesn't work with negatives"

addtimes_ :: Int -> Int -> [Int]
addtimes_ m n = if n > m
                then m : (addtimes_ (m+1) n) 
                else [n]

main = 
    print $ addtimes (10)

That will create a list with the numbers adding 1 consecutively

[1,2,3,4,5,6,7,8,9,10]

Upvotes: 1

Related Questions