@yatima2975 is dead right, there's a much easier way to do this as he has shown.
I'm going to write an answer though just because there's a couple things you're doing which you should be corrected of early as being the wrong approach in haskell.
| nChars <= 1 = nChars == 1
| nChars == 2 = firstElem == lastElem
In both these cases you're using a guard statement to check the length of an array, in haskell it's much more idiomatic to use matching to create cases for specific lengths, like so:
isPalindrome [] = False
isPalindrome [a] = True
isPalindrome [a,b] = a == b
Also:
| firstElem == lastElem = isPalindrome (take (nChars - 2) (tail w))
Here you're doing math on the length, when all you need is the init and the tail, also this is your last case so you can simplify it using otherwise. But you don't even need to use a guard statement here because it's an and operation.
isPalindrome w = (head w == last w) && isPalindrome middle
where middle = (init . tail) w
Learn your head/last/init/tail functions and get used to remember to use those. They work like so:
Head=1
|
| __________Tail=[2,3,4,5]
||
[1,2,3,4,5]
[1,2,3,4]=Init________||
|
|
5=Last
All of that said, the correct way to do this is the implementation detailed by yatima.