title: Logging using the free monad
body: <p>This question is related to <a href="http://degoes.net/articles/modern-fp">this article</a> </p>
  
  <p>The idea is to define a DSL for manipulating files in the cloud, and define a
  composition of interpreters that take care of the different aspects, such as
  communication with the REST interface and logging.</p>
  
  <p>To make this more concrete, assume we have the following data structure that
  defines the terms of the DSL.</p>
  
  <pre><code>data CloudFilesF a
  = SaveFile Path Bytes a
  | ListFiles Path ([Path] -&gt; a)
  deriving Functor
  </code></pre>
  
  <p>We define functions to build CloudFiles programs as follows:</p>
  
  <pre><code>saveFile :: Path -&gt; Bytes -&gt; Free CloudFilesF ()
  saveFile path bytes = liftF $ SaveFile path bytes ()
  
  listFiles :: Path -&gt; Free CloudFilesF [Path]
  listFiles path = liftF $ ListFiles path id
  </code></pre>
  
  <p>Then the idea is to interpret this in terms of two other DSL's:</p>
  
  <pre><code>data RestF a = Get Path (Bytes -&gt; a)
           | Put Path Bytes (Bytes -&gt; a)
           deriving Functor
  
  data Level = Debug | Info | Warning | Error deriving Show
  data LogF a = Log Level String a deriving Functor
  </code></pre>
  
  <p>I managed to define a natural transformation from the CloudFiles DSL to the
  REST DSL with the following type:</p>
  
  <pre><code>interpretCloudWithRest :: CloudFilesF a -&gt; Free RestF a
  </code></pre>
  
  <p>Then given a program of the form:</p>
  
  <pre><code>sampleCloudFilesProgram :: Free CloudFilesF ()
  sampleCloudFilesProgram = do
    saveFile "/myfolder/pepino" "verde"
    saveFile "/myfolder/tomate" "rojo"
    _ &lt;- listFiles "/myfolder"
    return ()
  </code></pre>
  
  <p>It is possible to interpret the program using REST calls as follows:</p>
  
  <pre><code>runSampleCloudProgram =
    interpretRest $ foldFree interpretCloudWithRest sampleCloudFilesProgram
  </code></pre>
  
  <p>The problem comes when trying to define an interpretation of the DSL using
  logging. In the article I referred above, the author defines an interpreter
  with type:</p>
  
  <pre><code>logCloudFilesI :: forall a. CloudFilesF a -&gt; Free LogF ()
  </code></pre>
  
  <p>and we define an interpreter for <code>Free LogF a</code> having type:</p>
  
  <pre><code>interpretLog :: Free LogF a -&gt; IO ()
  </code></pre>
  
  <p>The problem is that this interpreter cannot be used in combination with
  <code>foldFree</code> as I did above. So the question is how to interpret a program in
  <code>Free CloudFilesF a</code> using the function <code>logCloudfilesI</code> and <code>interpretLog</code>
  defined above? Basically, I'm looking to construct a function with type:</p>
  
  <pre><code>interpretDSLWithLog :: Free ClouldFilesF a -&gt; IO ()
  </code></pre>
  
  <p>I can do this with the REST DSL, but I cannot do it usng <code>logCloudfilesI</code>. </p>
  
  <p>What is the approach taken when using free monads in these situations? Note
  that the problem seems to be the fact that for the logging case, there is no
  meaningful value we can supply to the function in <code>ListFiles</code> to build the
  continuation of the program. In a <a href="http://degoes.net/articles/modern-fp-part-2">second article</a>
   the author uses <code>Halt</code>, however,
  this does not work in my <a href="https://github.com/capitanbatata/sandbox/blob/master/free-monads/src/CloudFiles.hs">current implementation</a>.</p>