00-A-Bad-Program.purs

module BadProgram where

import Prelude

import Effect (Effect)
import Effect.Console (log)
import Effect.Random (randomInt)

main :: Effect Unit
main = do
  log "This is an example of a program that is written in an FP language, \
      \but which is terribly structured. Why? Because it's impossible to test \
      \or otherwise prove that the code works correctly. All of its pure \
      \business logic is intermixed with impure code that makes the \
      \program work."

  initialState <- randomInt 10 20
  int2 <- randomInt 5 20
  int3 <- randomInt 5 30

  let nextState = initialState + int2 * int3 / initialState

  int4 <- randomInt 200 900
  int5 <- randomInt 45 80
  int6 <- randomInt 2 3

  let finalState = nextState * int6 * int5 - int4 + initialState

  log $ "The final output of the program was: " <> show finalState

{-
There's a few issues with this program as it is currently written:

First, it's hard to test. How would you test this program to ensure
    it works properly?

Maybe we want to guarantee that the code will always produce
    a value that is even. Since all of our functions (i.e. the stuff
    we do before storing the next state) receive random integers,
    how could we ensure these functions are defined correctly?

Second, this program does not tell us whether an error can occur
    and, if so, where such an error would appear.

Third, what if we wanted to use a different random number generator
    than the one provided via `Effect.Random (randomInt)`? Let's say
    the first time we run the program, we do want to use 'randomInt.'
    If so, then this works. However, let's say the next time we run
    this program, we want it to use something more complex. Well,
    we don't have an easy way to quickly swap out a random number generator
    without changing our business logic.

Such problems as these will be fixed/improved if we structure our FP
programs using Modern FP Architecture that is covered in this folder.
-}