<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    <blockquote type="cite"
cite="mid:A2A20EC3B8560D408356CAC2FC148E53016CF58A05@SUN-DAG3.synchrotron-soleil.fr">
      <pre class="moz-quote-pre" wrap="">So I discribe a location in the tree, like this with another type quite similar to the first but with only
one child per group. This way there is only one dataset extracted.

(maybe later, I will discuss about extracting  multiple dataset ;).

data Hdf5Path sh e
  = H5RootPath (Hdf5Path sh e)
  | H5GroupPath ByteString (Hdf5Path sh e)
  | H5DatasetPath ByteString

hdf5p $ group "name" $ group "otherName" $ dataset "myDataset"

Is there a better way to do this sort of things.
</pre>
    </blockquote>
    <p><br>
    </p>
    <p>The answer to this depends a lot on how powerful you want your
      path to be.<br>
      But the easiest way would probably be to just wrap functions:</p>
    <pre> -- can be used with functions from Data.List
        data Path a = GroupPath ([Hdf5M a] -> Hdf5M a) (Path a) | …
        
        test  = hdf5p $ group head   $ group (firstOfName "otherName") $ dataset "mydataset"
        test2 = hdf5p $ group (!! 6) $ group (firstOfName "otherName") $ dataset "mydataset"
        firstOfName n = fromJust . (find $ hasName n)
        hasName :: ByteString -> Hdf5M a -> Bool
</pre>
    <p>Or if you want more restrictions on which types of paths can be
      constructed<br>
    </p>
    <pre> data Path a = GroupPathWithFilter (Hdf5M a -> Bool) (Path a) | GroupPathByIndex Int (Path a) …
        
        -- equivalent to "head"
        test  = hdf5p $ group (const True) $ group (hasName "otherName") $ dataset "mydataset"
        test2 = hdf5p $ groupAt 6 $ group (hasName "otherName") $ dataset "mydataset"       
</pre>
    <p>Side note: I don't see a reason why the path needs to be
      recursive if this is all you want.</p>
    <pre> type Path a = [PathSegment a]
        data PathSegment a = GroupPath (Hdf5M a -> Bool) | …
        
        test  = hdf5p [group (const True) , group (hasName "otherName") , dataset "mydataset"]
</pre>
    <p> What if you want something more like an XPath or a path with
      wildcards? You can still expand on these ideas easily.</p>
    <pre> type Path a = [PathSegment a]
        data PathSegment a = GroupPath ([Hdf5M a] -> [Hdf5M a]) | …
        
        test  = hdf5p [group (pure . head)   , group (filter $ hasName "otherName") , dataset "mydataset"]
        test2 = hdf5p [group (pure . (!! 6)) , group (filter $ hasName "otherName") , dataset "mydataset"]
        
        -- or more likely
        test  = hdf5p  [group head   , groups (hasName "otherName") , dataset "mydataset"]
        test2 = hdf5p' [group (!! 6) , groups (hasName "otherName") , dataset "mydataset"]

        -- But these are basically just lists of [Hdf5M a] → [Hdf5M a] functions with one special function
        -- at the end – which can also be cast as such a function. Therefore something like this would also be possible:
        newtype Path a = Path [[Hdf5M a] -> [Hdf5M a]]
        compilePath (Path fs) = filter isDataset . foldl1 (.) fs

        -- Path can also be turned into a monoid now
        test  = hdf5p $ group head <> groups (hasName "otherName") <> dataset "mydataset"
        
        -- which also means it would be prudent to reduce this to
        newtype Path a = Path ([Hdf5M a] -> [Hdf5M a])</pre>
    <p><br>
      While this final solution looks quite elegant from my POV, there
      are several directions this can't be extended into as easily as
      the recursive tree.</p>
    <p>So this is just a bunch of options from a few minutes of
      brainstorming, the best option for your particular problem is
      probably somewhere between these and the ones you already had.</p>
    <p>Cheers.<br>
    </p>
  </body>
</html>