Home > Enterprise >  Create a function that takes a string (some sentence) and split it into list of tuples (word, length
Create a function that takes a string (some sentence) and split it into list of tuples (word, length

Time:11-23

Create a function that takes a string and splits it into list of tuples of type (word, length word). It needs to be done using foldr through one pass of the list, without using length and/or ( ).

For example

> splitSen "    Asdf  qw   zx     mn      "
[("Asdf",4),("qw",2),("zx",2),("mn",2)]

My implementation looks like that

splitSen :: String -> [(String,Int)]
splitSen cs = foldr func [] cs where
  func ' ' ((c1,n1) : ps) = ps
  func c ((c1,n1) : ps) = (c:c1,1 n1):ps

And I get an error

*** Exception: Non-exhaustive patterns in function func

But can not figure out what pattern I am missing.

CodePudding user response:

Let's turn warnings on! This can be done with the -Wall flag.

$ ghci -Wall
> :{
| splitSen :: String -> [(String,Int)]
| splitSen cs = foldr func [] cs where
|   func ' ' ((c1,n1) : ps) = ps
|   func c ((c1,n1) : ps) = (c:c1,1 n1):ps
| :}

<interactive>:6:3: warning: [-Wincomplete-patterns]
    Pattern match(es) are non-exhaustive
    In an equation for ‘func’:
        Patterns not matched:
            p [] where p is not one of {' '}
            ' ' []

<interactive>:6:14: warning: [-Wunused-matches]
    Defined but not used: ‘c1’

<interactive>:6:17: warning: [-Wunused-matches]
    Defined but not used: ‘n1’

Above, the warning tells that the empty list case [] is not handled in func.

CodePudding user response:

In case someone ever will have something similar here what I managed to make

splitSen = fst . foldr func ([], True) where
  func ' ' ([], _) = ([], True)
  func c ([],bool) | bool = ([([c],1)], False)
  func ' ' (((word, len):rest), bool) = (((word, len):rest), True)
  func c (y@((word, len):rest), bool) | bool = (([c],1):y, False) 
                    | otherwise = (((c:word, 1 len):rest), False)

Looks really bad but works...

  • Related