<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    <div class="moz-cite-prefix">Hi.</div>
    <div class="moz-cite-prefix"><br>
    </div>
    <blockquote type="cite"
cite="mid:A2A20EC3B8560D408356CAC2FC148E53016CF57EB5@SUN-DAG3.synchrotron-soleil.fr">
      <pre class="moz-quote-pre" wrap="">I end up with this type.

data Hdf5M a
  = H5Root (Hdf5M a)
  | H5Group ByteString [Hdf5M a]  -- A group can contain other groups and/or datasets
  | forall sh b. (NativeType b, Shape sh) => H5Dataset ByteString (Array F sh b)

[…]

And I would like to be able to describe a contain like this

hdf5 $ do
      group "name" $ do
            dataset "name1" array1
            dataset "name2" array2
            group "other-name" $ do
                     etc...
</pre>
    </blockquote>
    <p>You don't need a monad instance for this. First of all, you don't
      even need do syntax to make something "pretty" similar to this.</p>
    <pre class="moz-quote-pre" wrap="">       hdf5 $
            group "name" $
                [ dataset "name1" array1
                , dataset "name2" array2
                , group "other-name" $ [
                    …</pre>
    <p>But if you insist, you can just use an existing monad like
      WriterT. For example (simplified):</p>
    <pre> data Composite a = Base a | Composite [Composite a]
        
        type CompositeWriter a = Writer [Composite a] ()
        
        base = tell . pure . Base
        
        composite = censor (pure . Composite)
        
        asComposite = Composite . snd . runWriter
        
        test = asComposite $ do
            base 'a'
            base 'b'
            composite $ do
              base 'c'
              base 'd'
</pre>
    <p>Hope that helps.<br>
    </p>
  </body>
</html>