It might take some time to get your head round Haskell and Prolog and whatever else, but that's worth doing. Here's an analogy to get you started on declarative vs imperative.
Let's imagine you want to find out what 5sin(7x+20)+cos(x) is when x is 5.279 and all you've got is your calculator. If it's an old calculator, you have to tell it how to do it and in what order. If we use MC
for clear memory to 0 and MR
for recall memory and M+
for add the current number to the one in memory, what you actually type is
MC -- clear the memory
5.279 -- take the number 5.279
*7= -- multiply it by seven
+20= -- add twenty
sin= -- find sin of that
*5= -- times by five
M+ -- store that in the memory
5.279 -- take the number 5.279
cos -- find cos of it
M+ -- add that to what you had in the memory
MR -- get the total back out of memory onto the screen
You're telling the calculator step-by-step what calculations to do because it hasn't been programmed to understand maths, just arithmetic. The structure of what you're calculating has been obscured by turning it into steps. Some people like this step-by-step way of doing it, find it very straightforward and can't understand why other people can be bothered doing it any other way. It works. You don't have to trust the calculator.
Now any programming language and any modern calculator will let you type
5*sin(7*5.279+20)+cos(5.279)
which is much clearer and some calculators bought in the last decade will even let you do
5.279 -> x
5sin(7x+20)+cos(x)
Modern calculators let you express the problem in terms of your own understanding instead of breaking it down into steps for the calculator. Some people like this just-say-what-you-mean way of doing it, find it very straightforward and can't understand why other people can be bothered doing it any other way. It's clear. You don't have to explain to the calculator.
Although this 5.279 -> x; 5sin(7x+20)+cos(x)
is almost exactly how you would solve this particular problem in an imperative programming language, we're talking about styles of calculator just now, and the first way of doing it with the old calculator is much more imperative (step-by-step) in style, and this with the new calculator is in a much more declarative (just-say-what-you-mean) style.
Let's change context and instead of using a calculator to work out a number, we're using some felt tips to draw a simple nonsense picture. Let's assume we always start at the top left corner when we measure. The imperative (step-by-step) style would be
take a piece of paper 7 by 10
pick up a red pen
put it at the point (3,4)
draw a 2x4 rectangle here
colour it in
pick up a black pen
put it at the point (4,4)
draw a circle here radius 3
colour it in
whereas the declarative just-say-what-you-mean style would be
on a piece of paper 7 by 10
red 2x4 rectangle at (3,4)
underneath
black circle radius 3 at (4,4)
These aren't examples of imperative or declarative code, but an attempt to show you the differences in style of thinking and programming. In declarative programming you say what you mean, then use a necessarily very clever compiler to transform your declarations into the optimum sequence of instructions. Because you've said what you mean it can radically change the code that achieves this into the most efficient form whilst preserving your meaning. You trust the compiler.
In imperative programming you say step-by-step what you want to do, making sure yourself that you've used the most efficient method you can think of, then the compiler uses a couple of tricks to eliminate unnecessary slowness and translates into a lower-level sequence of instructions. Because you've specified what order to do things, there's a limit to how much optimisation it can do, but you trust the programmer to have made the best choice already.
(I've talked about trust because someone who read a draft of this said trust was important - she explains she uses the calculator the imperative way because she doesn't really trust it if she does it in the declarative way. I think that's the same for programmers. Many programmers don't trust compilers enough to be declarative - they want the control, and like to optimise their code themselves.)
It sounds from this that it would be much easier to use declarative styles all the time, but there's usually a steep learning curve for declarative languages, and most people prefer imperative. Traditionally there was a huge difference in speed (imperative has fewer overheads because it's more directly like the computer works), but some more modern compilers of declarative code seem to be in the top few of the speed tables a lot of the time - compiled verses interpreted makes a much bigger difference than imperative vs declarative, which is why python etc are often slower even though they're imperative.