title: How to properly convert the list of files into a recursive record in Haskell?
body: <p>I have a following list of filenames and their content:</p>
  <pre><code>list :: [(TreeFilePath, String)]
  list = [
      (&quot;dir1/content1&quot;,&quot;1&quot;),
      (&quot;dir1/content11&quot;,&quot;11&quot;),
      (&quot;dir1/dir1/content1&quot;,&quot;1++&quot;),
      (&quot;dir1/dir1/content11&quot;,&quot;11++&quot;),
      (&quot;dir2/content2&quot;,&quot;2&quot;),
      (&quot;dir2/content21&quot;,&quot;21&quot;),
      (&quot;dir2/dir2/content2&quot;,&quot;2++&quot;),
      (&quot;dir2/dir2/content21&quot;,&quot;21++&quot;)
  ]
  </code></pre>
  <p>I want to convert it into a following recursive structure:</p>
  <pre><code>data Content = Content {
    content :: Either (Map TreeFilePath Content) String
  } deriving (Eq, Show) 
  </code></pre>
  <p>Here is how I am trying to do that:</p>
  <pre><code>pathsToContent :: [(TreeFilePath, String)] -&gt; IO Content
  pathsToContent [] = return $ Content $ Right &quot;&quot;
  pathsToContent a@((fullPath, content):xs) = 
    let generatedContent = generateContentFromPathList pathList content
     in do
        processedContent &lt;- pathsToContent xs 
        insertIntoContent processedContent generatedContent 
  
  insertIntoContent :: Content -&gt; Content -&gt; IO Content
  insertIntoContent a@(Content existingContent) b@(Content contentToAdd) = 
    do
      case existingContent of
        Right s -&gt; do
          if (L.null s) then case contentToAdd of 
            Right _ -&gt; return a 
            Left _ -&gt; return b
          else return a
        Left m -&gt; case contentToAdd of
          Right sa -&gt; do
            if L.null sa then return a else insertIntoContent (Content $ Left $ insert (BS.pack sa) b m) b
          Left ma -&gt; do
            if Data.Map.null ma then return a else 
              let filtered = Data.Map.foldrWithKey(\k a v -&gt; case Data.Map.lookup k ma of Nothing -&gt; v; Just f -&gt; case content f of Right fs -&gt; v; Left fm -&gt; union fm v) Data.Map.empty m 
                  key = Data.Map.foldrWithKey(\k a v -&gt; case Data.Map.lookup k ma of Nothing -&gt; v; Just f -&gt; k) &quot;&quot; m 
                  without = Data.Map.foldrWithKey(\k a v -&gt; case Data.Map.lookup k m of 
                      Nothing -&gt; case content a of 
                        Right fs -&gt; v
                        Left fm -&gt; union ma v
                      Just f -&gt; v
                    ) Data.Map.empty ma 
               in do
                insertIntoContent (Content $ Left $ 
                  if BS.null key 
                     then union m without 
                     else adjust (\a -&gt; 
                       case content a of 
                         Right s -&gt; Content $ Right s; 
                         Left am -&gt; Content $ Left $ union am filtered
                       ) key m
                    ) (if BS.null key then Content $ Left without else Content $ Right &quot;&quot;)
  </code></pre>
  <p>The problem with this code is that it does not do nested detection of parent directory to merge the child content to. If I run the following command:</p>
  <pre><code>pathsToContent list
  </code></pre>
  <p>I get the following result:</p>
  <pre><code>Content {content = Left (fromList [
      (&quot;dir1&quot;,Content {content = Left (fromList [
            (&quot;content1&quot;,Content {content = Right &quot;1&quot;}),
            (&quot;content11&quot;,Content {content = Right &quot;11&quot;}),
            (&quot;dir1&quot;,Content {content = Left (fromList [
                  (&quot;content11&quot;,Content {content = Right &quot;11++&quot;})
            ])})
      ])}),
      (&quot;dir2&quot;,Content {content = Left (fromList [
            (&quot;content2&quot;,Content {content = Right &quot;2&quot;}),
            (&quot;content21&quot;,Content {content = Right &quot;21&quot;}),
            (&quot;dir2&quot;,Content {content = Left (fromList [
                  (&quot;content21&quot;,Content {content = Right &quot;21++&quot;})
            ])})
      ])})
  ])}
  </code></pre>
  <p>As you can see, files <code>dir1/dir1/content1</code> and <code>dir2/dir2/content2</code> were omitted from the result. I cannot figure out how to properly manage adding handling of such case into the conversion algorithm. If you have any ideas how to make it works, I would really appreciate it. Thanks!</p>