Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>The two nested loops you wrote are an excellent starting point. That is, we can write a function <code>tokens</code> that delegates its work to two recursive functions <code>outer</code> and <code>inner</code> that correspond to your loops:</p> <pre><code>type Token a = ([a], Int, Int) tokens :: [a] -&gt; [Token a] tokens = outer 0 where outer _ [] = [] outer i l@(_ : xs) = inner i [] l ++ outer (i + 1) xs where inner _ _ [] = [] inner j acc (x : xs) = (acc ++ [x], i, j) : inner (j + 1) (acc ++ [x]) xs </code></pre> <p>Here, <code>outer</code> iterates over the string and, for each start position within that string, calls <code>inner</code> to collect all the segments that start at that position together with their end positions.</p> <p>Although this function meets your requirements,</p> <pre><code>&gt; tokens "blah" [("b",0,0),("bl",0,1),("bla",0,2),("blah",0,3),("l",1,1),("la",1,2),("lah",1,3),("a",2,2),("ah",2,3),("h",3,3)] </code></pre> <p>it is quite inefficient due to the repeated list concatenation. A more efficient version would accumulate its results in so-called <a href="http://www.haskell.org/haskellwiki/Difference_list" rel="nofollow">difference lists</a>:</p> <pre><code>type Token a = ([a], Int, Int) tokens :: [a] -&gt; [Token a] tokens l = outer 0 l [] where outer _ [] = id outer i l@(_ : xs) = inner i id l . outer (i + 1) xs where inner _ _ [] = id inner j acc (x : xs) = ((acc [x], i, j) :) . inner (j + 1) (acc . (x :)) xs </code></pre> <p>How to construct the dictionary of course depends on how you choose to represent it. Here's an approach that uses simple ordered association lists,</p> <pre><code>type Dict a = [([a], [(Int, Int)])] empty :: Dict a empty = [] update :: Ord a =&gt; Token a -&gt; Dict a -&gt; Dict a update (xs, i, j) [] = [(xs, [(i, j)])] update (xs, i, j) ((ys, ns) : dict) = case compare xs ys of LT -&gt; (xs, [(i, j)]) : (ys, ns) : dict EQ -&gt; (ys, (i, j) : ns) : dict GT -&gt; (ys, ns) : update (xs, i, j) dict toDict :: Ord a =&gt; [a] -&gt; Dict a toDict = foldr update empty . tokens </code></pre> <p>but as your keys are strings, <a href="http://en.wikipedia.org/wiki/Trie" rel="nofollow">tries</a> (a.k.a. prefix trees) are probably a better choice.</p> <p>If it's efficient substring queries that you're after, I would recommend looking into <a href="http://en.wikipedia.org/wiki/Suffix_tree" rel="nofollow">suffix trees</a>, although their implementation is somewhat involved. You may want to check out</p> <ul> <li>Robert Giegerich and Stefan Kurtz. A comparison of imperative and purely functional suffix tree constructions. <em>Science of Computer Programming</em> 25(2–3):187–218, 1995</li> </ul> <p>and Bryan O'Sullivan's <a href="http://hackage.haskell.org/package/suffixtree" rel="nofollow">suffixtree</a> package on Hackage.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload