I often find myself writing functions that look like this because they
allow me to easily mock data access, and still provide a signature that accepts parameters to determine what data to access.

 public static string GetFormattedRate(
 Func<string, RateType>> getRate,
 string rateKey)
 {
 var rate = getRate(rateKey);
 var formattedRate = rate.DollarsPerMonth.ToString("C0");
 return formattedRate;
 }

Or

 public static string GetFormattedRate(
 Func<RateType, string> formatRate,
 Func<string, RateType>> getRate,
 string rateKey)
 {
 var rate = getRate(rateKey);
 var formattedRate = formatRate(rate);
 return formattedRate;
 }

Then I use it something like this:

 using FormatterModule;

 public static Main()
 {
 var getRate = GetRateFunc(connectionStr);
 var formattedRate = GetFormattedRate(getRate, rateType);
 // or alternatively
 var formattedRate = GetFormattedRate(getRate, FormatterModule.FormatRate, rateKey);
 
 System.PrintLn(formattedRate);
 }

Is this a common practice? I feel like I should be doing something more like

 public static string GetFormattedRate(
 Func<RateType> getRate())
 {
 var rate = getRate();
 return rate.DollarsPerMonth.ToString("C0");
 }

But that doesn't seem to work very well because I'd have to make a new function to pass into the method for every rate type.

Sometimes I feel like I should be doing

 public static string GetFormattedRate(RateType rate)
 {
 return rate.DollarsPerMonth.ToString("C0");
 }

But that seems to take away any fetch and format re-usability. Whenever I want to fetch and format I have to write two lines, one to fetch and one to format.

What am I missing about functional programming? Is this the right way to do it, or is there a better pattern that's both easy to maintain and use?