I have a list of n-bit "words"
type BitWord = [Bool]
and a trie which stores the word from the top to bottom:
data Tree = Bs Tree Tree -- Bs (zero_bit) (one_bit)
| X -- incomplete word
| B -- final bit of word
I have a function:
seenPreviously :: BitWord -> Tree -> (Tree,Bool)
The function steps through the bits in the BitWord
, while descending through the Tree
going left at a zero bit and vice versa. We return a new tree with this BitWord
"merged in", along with True if we had to add subtrees at some point (i.e. the BitWord
was not in the trie already) and False otherwise.
I map this function over a [BitWord]
, passing the Tree as state.
My question is this: Could this benefit from parallelism offered by Control.Parallel? And if so, how can I reason about laziness and evaluation only to weak head normal form, etc.?
My instinct is that I can be inserting (actually building a subtree) down a left branch while doing the same thing down the right branch, as two independent threads. Something like:
parallelMapSt :: [ BitWords ] -> Tree -> [Bool]
parallelMapSt [] _ = []
parallelMapSt (w:ws) t = let (b,t') = seenPreviously w t
bs = parralelMapSt ws t'
in t' `par` bs `pseq` (b:bs)
The thread evaluating b
is dependent on some previously sparked threads (the ones belonging to the BitWords
that share some common prefix with w
), but not all of them, so it would seem that there is opportunity to do work in parallel here, but I'm really not sure.