Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell: Deleting white space from a list of strings

The question is: Write a function that will delete leading white space from a string. Example: cutWhitespace [" x","y"," z"] Expected answer: ["x","y","z"]

Heres what I have:

cutWhitespace (x:xs) = filter (\xs -> (xs /=' ')) x:xs

This returns ["x", " y"," z"] when the input is [" x"," y", " z"]. Why is it ignoring the space in the second and third string and how do I fix it?

We are allowed to use higher-order functions which is why I implemented filter.

like image 321
Alowishious Avatar asked Jan 02 '23 17:01

Alowishious


2 Answers

The reason the OP cutWhitespace function only works on the first string, is that due to operator precedence, it's actually this function:

cutWhitespace (x:xs) = (filter (\xs -> (xs /=' ')) x) : xs

Here, I've put brackets around most of the body to make it clear how it evaluates. The filter is only applied on x, and x is the first element of the input list; in the example input " x".

If you filter " x" as given, you get "x":

Prelude> filter (\xs -> (xs /=' ')) " x"
"x"

The last thing cutWhitespace does, then, is to take the rest of the list ([" y", " z"]) and cons it on "x", so that it returns ["x"," y"," z"].

In order to address the problem, you could write the function with the realisation that a list of strings is a nested list of characters, i.e. [[Char]].

As a word of warning, pattern-matching on (x:xs) without also matching on [] is dangerous, as it'll fail on empty lists.

like image 118
Mark Seemann Avatar answered Jan 05 '23 06:01

Mark Seemann


Instead of writing a custom function that checks if a character is whitespace, I would advice to use isSpace :: Char -> Bool. This function does not only returns True for a space (' '), but for a new line ('\n'), a carriage return ('\r'), a tab ('\t'), a vertical tab ('\v') and form feed ('\f') as well. Usually it is better to work with such functions since the odds of forgetting certain cases is lower.

We can thus remove the spacing of a single string with:

dropWhile isSpace

Where we thus dropWhile in such way that all chacters where isSpace.

We can then perform a mapping with this filter to filter the spaces out of all the strings, like:

import Data.Char(isSpace)

cutWhitespace = map (dropWhile isSpace)
like image 28
Willem Van Onsem Avatar answered Jan 05 '23 06:01

Willem Van Onsem