Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'Auxiliary' function in Haskell

My lecturer at the moment has a strange habit I've not seen before, I'm wondering if this is a Haskell standard or a quirk of his programming style.

Basically, he'll often do thing such as this:

functionEx :: String -> Int
functionEx s = functionExA s 0

functionExA :: String -> Int -> Int
functionExA s n = --function code

He calls these 'auxiliary' functions, and for the most part the only advantage I can see to these is to make a function callable with fewer supplied arguments. But most of these are hidden away in code anyway and in my view adding the argument to the original call is much more readable.

As I said, I'm not suggesting my view is correct, I've just not seen it done like this before and would like to know if it's common in Haskell.

like image 585
Overt_Agent Avatar asked Mar 11 '23 10:03

Overt_Agent


1 Answers

Yes, this is commonplace, and not only in functional programming. It's good practice in your code to separate the interface to your code (in this case, that means the function signature: what arguments you have to pass) from the details of the implementation (the need to have a counter or similar in recursive code).

In real-world programming, one manifestation of this is having default arguments or multiple overloads of one function. Another common way of doing this is returning or taking an instance of an interface instead of a particular class that implements that interface. In Java, this might mean returning a List from a method instead of ArrayList, even when you know that the code actually uses an ArrayList (where ArrayList implements the List interface). In Haskell, typeclasses often serve the same function.

The "one argument which always should be zero at the start" pattern happens occasionally in the real world, but it's especially common in functional programming teaching, because you want to show how to write the same function in a recursive style vs. tail-recursive. The wrapper function is also important to demonstrate that both the implementations actually have the same result.

In Haskell, it's more common to use where as follows:

functionEx :: String -> Int
functionEx s = functionExA s 0 where
    functionExA s n = --function code

This way, even the existence of the "real" function is hidden from the external interface. There's no reason to expose the fact that this function is (say) tail-recursive with a count argument.

like image 62
Dan Hulme Avatar answered Mar 16 '23 23:03

Dan Hulme