They aren't different types of waiting, WebDriverWait is a specialized version of FluentWait with some different constructor options.
In the WebDriver java library, there are 3 types in the inheritance tree of WebDriverWait:
Wait is a generic interface for waiting until a condition is true or not null. Very basic and doesn't define how any of this is done.
FluentWait is an implementation of the Wait interface that may have its timeout and polling interval configured on the fly. This class is generic and requires a type <T>
WebDriverWait extends FluentWait and is a specialization that uses WebDriver instances.
Prefer WebDriverWait over FluentWait when your generic type <T> would be <WebDriver>. It aims to ease construction.
Given this instance of WebDriverWait
WebDriverWait wait = new WebDriverWait(driver, 30);
This is what an equivalent FluentWait looks like to create
FluentWait<WebDriver> wait = new FluentWait<>(driver, new SystemClock(), Sleeper.SYSTEM_SLEEPER);
wait.withTimeout(Duration.ofSeconds(30));
wait.pollingEvery(Duration.ofMillis(500));
wait.ignoring(NotFoundException.class);
This is as far as the difference goes. The resulting object will behave the same. WebDriverWait just gives you those defaults for free.