Advice on Learning “How to Think Functional”?

后端 未结 5 2079
慢半拍i
慢半拍i 2021-01-31 11:56

As a newbie in functional languages (I started touching Erlang a couple of weeks ago -- the first functional language I could get my hands on).

I started to writing some

5条回答
  •  谎友^
    谎友^ (楼主)
    2021-01-31 12:37

    After a while, I found that functional programming [...] encourages a "top down" design.

    Well, it's not about "top down" or "bottom up" design really. It's about focusing on the "what" of the problem at hand, rather than the "how". When I started off with functional programming, I found that I kept recalling imperative constructs like the nested for loop in C. Then I quickly found out that trying to translate my imperative thinking to functional constructs was very difficult. I'll try to give you a more concrete example. I'll implement an equivalent program in C and Haskell and attempt to trace my thought process in both cases. Note that I've been explicitly verbose for the purpose of explanation.

    In C:

    #include 
    
    int main(void)
    {
      int i, inputNumber, primeFlag = 1;
      scanf("%d", &inputNumber);
      for(i = 2; i <= inputNumber / 2; i ++)
        {
          if (inputNumber % i == 0)
            {
              primeFlag = 0;
              break;
            }
        }
      if (primeFlag == 0) printf("False\n");
      else printf ("True\n");
      return 0;
    }
    

    Trace of my thought process:

    1. Think in steps. First, accept a number from the user. Let this number be called inputNumber. scanf() written.
    2. Basic algorithm: A number is prime unless otherwise proven. primeFlag declared and set equal to 1.
    3. Check primeNumber against every number from 2 to primeNumber/2. for loop started. Declared a loop variable i to check primeNumber against.
    4. To disprove our initial assertion that the number is prime, check primeNumber against each i. The moment we find even one i that divides primeNumber, set primeFlag to 0 and break. Loop body written.
    5. After going through our rigorous checking process in the for loop, check the value of primeFlag and report it to the user. printf() written.

    In Haskell:

    assertPrime :: (Integral a) => a -> Bool
    assertPrime x = null divisors
        where divisors = takeWhile (<= div x 2) [y | y <- [2..], mod x y == 0]
    

    Trace of my thought process:

    1. A number is prime if it has no divisors but one and itself. So, null divisors.
    2. How do we build divisors? First, let's write down a list of possible candidates. Wrote down Texas range from 2 to number/2.
    3. Now, filter the list, and pick out only items that are really divisors of the number. Wrote the filter mod x y == 0

    I want to get advice about how to "think in functional language"

    Ok, first and foremost, think "what", not "how". This can take a lot of practice to get used to. Also, if you were formerly a C/C++ programmer like me, stop worrying about memory! Modern languages have a garbage collector, and it's written for you to use- so don't even try to modify variables in place. Another thing that has personally helped me: write down English-like definitions in your program to abstract out the functions that do the heavy-lifting.

提交回复
热议问题