Create a function that takes a string and splits it into list of tuples of type
(word, length word)
. It needs to be done usingfoldr
through one pass of the list, without usinglength
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...