Mampenda
Mampenda

Reputation: 671

How do i syntax in haskell

Im trying to write a function that takes in a string and then returns the string as a list of string-words (like the words built-in function) and so far i've written

ord :: String -> [String]
ord [] = []
ord xs = let
    ys = groupBy (\x y -> y /= ' ') xs
    in filter (not . null) ys

I thougth this would get rid of the empty strings from the list but i only get this output

input:

ord  “aa b       c   -    dd” 

output:

["aa"," b"," "," "," "," "," "," "," c"," "," "," -"," "," "," "," dd"]

when this is the output i want:

[“aa”, ”b”, ”c”, ”-“, ”dd”]

I get the same result if i try and write

ord :: String -> [String]
ord [] = []
ord xs = filter (not . null) ys
    where
        ys = groupBy (\x y -> y /= ' ') xs

How do i re-write this code so that i rid the list of its empty strings? Or use the proper syntax? Im just learning Haskell and im still having trouble with the syntax...

Upvotes: 2

Views: 193

Answers (2)

dfeuer
dfeuer

Reputation: 48581

I wouldn't bother with groupBy at all here. In particular, there's no need to build lists of spaces just to throw them away. Let's start with a function that drops initial spaces and then grabs everything to the first space:

grab :: String -> (String, String)
grab = break isSpace . dropWhile isSpace

Note that the first component of grab xs will be empty if and only if all the elements of xs are spaces.

Now we can write

myWords :: String -> [String]
myWords xs = case grab xs of
  ([], _) -> []
  (beginning, end) -> beginning : myWords end

Upvotes: 3

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476557

groupBy means that you put x and y in the same group, given the condition is satisfied. But here you group the two together, given y is not equal to a space.

You thus can alter your grouping predicate, and put x and y in the same group, given both are spaces, or non-spaces:

import Data.Char(isSpace)

ord :: String -> [String]
ord [] = []
ord xs = let
    ys = groupBy (\x y -> isSpace x == isSpace y) xs
    in filter (not . null) ys

or shorter:

import Data.Char(isSpace)
import Data.Function(on)

ord :: String -> [String]
ord [] = []
ord xs = let
    ys = groupBy (on (==) isSpace) xs
    in filter (not . null) ys

Now we retrieve:

Prelude Data.List> ord "aa b       c   -    dd"
["aa"," ","b","       ","c","   ","-","    ","dd"]

We of course still not obtain the expected result. In stead of filtering out empty strings, we can filter out strings that only contain spacing characters:

import Data.Char(isSpace)
import Data.Function(on)

ord :: String -> [String]
ord [] = []
ord xs = let
    ys = groupBy (on (==) isSpace) xs
    in filter (not . all isSpace) ys

We do not need to covert the empty case manually, since groupBy on an empty list produces an empty list, we can thus construct a one liner to do the processing:

import Data.Char(isSpace)
import Data.Function(on)

ord :: String -> [String]
ord = filter (not . all isSpace) . groupBy (on (==) isSpace)

Then we obtain the expected result:

Prelude Data.List Data.Char> ord "aa b       c   -    dd"
["aa","b","c","-","dd"]

Upvotes: 5

Related Questions