Programs written in, for example, Java rely a lot on dynamic dispatch.
How are such programs expressed in functional languages such as Haskell?
In other word
It's surprising how often you don't actually need dynamic dispatch, just polymorphism.
For example, if you're going to write a function that sorts all the data in a list, you want it to be polymorphic. (I.e., you do not want to have to reimplement this function for every single type, by hand. That would be bad.) But you don't actually need anything dynamic; you know at compile-time what's actually in the list or lists you want sorted. So you don't actually need run-time type lookup at all in this case.
In Haskell, if you just want to move stuff around and you don't need to know or care what type it is, you can use so-called "parametric polymorphism", which is roughly something like Java generics or C++ templates. If you need to be able to apply a function to the data (e.g., to sort data you need order comparisons), you can pass the function to do that in as an argument. Alternatively, Haskell has a thing that's a bit like a Java interface, and you can say "this sorting function accepts any type of data that implements this interface".
So far, no dynamic dispatch at all, only static. Note also that since you can pass functions as arguments, you can do "dispatch" manually by hand.
If you really need actual dynamic dispatch, you can use "existential types", or you can use the Data.Dynamic
library, and similar tricks.