Search code examples
haskellfunctional-programming

Intercalate function


I'm learning Haskell and I wanted to do a function where it receives two numbers and it intercalates between positive and negative. Thanks for your help. example:

intercalarNum 5 2 = [2,-2,2,-2,2]

Tried to do it many ways but ghci says it has a error everytime so I dont know what do do anymore

intercalarNum :: (Num a , Ord a ) => a -> a -> [a]
intercalarNum 0 y = []
intercalarNum x y = y : intercalarnumAux  (intercalarNum (x-1) y)
intercalarnumAux :: (Num a , Ord a ) => a -> a 
intercalarnumAux x | x < 0 = -x 
                   | x > 0 = -x 
                   | x == 0 = 0 

Solution

  • Let's start form this part:

    intercalarnumAux :: (Num a , Ord a ) => a -> a 
    intercalarnumAux x | x < 0 = -x 
                       | x > 0 = -x 
                       | x == 0 = 0
    

    Now, that very last 0 can also be written as -0, and since x==0, that can also be written as -x. If we choose to do that, we get

    intercalarnumAux :: (Num a , Ord a ) => a -> a 
    intercalarnumAux x | x < 0  = -x 
                       | x > 0  = -x 
                       | x == 0 = -x
    

    hence we discover that the result is -x in all cases! We could simply write

    intercalarnumAux :: (Num a , Ord a ) => a -> a 
    intercalarnumAux x = -x
    

    or even

    intercalarnumAux :: (Num a) => a -> a 
    intercalarnumAux x = -x
    

    We could also not define this function at all, and simply use uniry minus (aka negation) - .... as needed.

    Now, let's examine the main routine:

    intercalarNum :: (Num a , Ord a ) => a -> a -> [a]
    intercalarNum 0 y = []
    intercalarNum x y = y : intercalarnumAux  (intercalarNum (x-1) y)
    

    This actually looks rather good. While it is still wrong as you discovered trying to compile it, it gets most things correct.

    The base case where the first argument is 0 is correct.

    The inductive case starts the output list as y : ..., which is correct. It also decrements x in the recursive call, passing x-1 which is correct.

    Now, there is one last thing to fix. You are very close, so let me give you a hint. Right now you call intercalarnumAux (intercalarNum (x-1) y) which means - (intercalarNum (x-1) y) but you can't negate a list like that. Try to negate a number instead. Well, don't negate x-1 since decrementing that is correct. Can you spot some other number to negate? Just remember to use parentheses as in (- somethingToNegateHere), otherwise the minus sign could be interpreted as binary subtraction.