I'm quite new to Haskell and I'm trying to solve the following problem:
I have a function, that produces an infinite list of strings with different lengths. But the number of strings of a certain length is restricted.
Now I want to extract all substrings of the list with a certain length n . Unfortunately I did a lot of research and tried a lot of stuff, but nothing worked for me.
I know that filter()
won't work, as it checks every part of the lists and results in an infinite loop.
This is my function that generates the infinite list:
allStrings = [ c : s | s <- "" : allStrings, c <- ['R', 'T', 'P']]
I've already tried this:
allStrings = [x | x <- [ c : s | s <- "" : allStrings,
c <- ['R', 'T', 'P']], length x == 4]
which didn't terminate.
Thanks for your help!
This
allStrings4 = takeWhile ((== 4) . length) .
dropWhile ((< 4) . length) $ allStrings
does the trick.
It works because your (first) allStrings
definition cleverly generates all strings containing 'R'
, 'T'
, and 'P'
letters in productive manner, in the non-decreasing length order.
Instead of trying to cram it all into one definition, separate your concerns! Build a solution to the more general problem first (this is your allStrings
definition), then use it to solve the more restricted problem. This will often be much simpler, especially with the lazy evaluation of Haskell.
We just need to take care that our streams are always productive, never stuck.