title: New to F# - unobtrusive logging through bind-like (>>=!) infix operators and quotations?
body: <p>First of all, sorry for my poor English I'll do my best to make myself clear but if something doesn't make sense just point it out and I'll try to reformulate it. This question would be huge, it's my first time asking for help about programming (up until now I always found a solution on google or came up with something that does the trick), in this case, I have nor the knowledge of the language nor the time to go through the learning process and really need some experienced advice (originally posted on Reddit: <a href="https://www.reddit.com/r/fsharp/comments/con2aj/new_to_f_help_with_unobtrusive_logging/" rel="nofollow noreferrer">https://www.reddit.com/r/fsharp/comments/con2aj/new_to_f_help_with_unobtrusive_logging/</a> coming to SO for larger support).</p>
  
  <p><strong><em>TL;DR; I struggle with infix operators for monadic composition, leveraging Railway Oriented Programming but being unable to retrieve method information for sort of an AOP logging. I really want to know if there is a way to combine automatic quotations with infix operators or if there is another form of obtaining meta-information about functions in an infix bind-like operation or normal let-binding prefix one (without the need of static members). I'm not particularly worried about performance because this is not something that would be always running, it's more like a debug level logging used for specific cases.</em></strong></p>
  
  <hr>
  
  <h2><strong>Some background:</strong></h2>
  
  <p>I'm completely new to F#, I have 7 years of experience in a variety of language (including a little of C#) and love functional programming from the very beginning but never had the opportunity to use it in my work. Now I have the chance to use F# for a data transformations pipeline and I really want to make a good impression.</p>
  
  <p>So I've been playing with F# for about three weeks now, I get some of the building blocks of my small app done, and am having some headache with crosscutting concerns, in particular, logging. I really love the AOP (Aspect Oriented Programming) approach to logging (not messing the logic and instead decorate functions) and want to use something similar in F#. I do my research and it appears that computation expressions are the way to go (or at least that's what always pop up in AOP F# searches)... but I really love to chain operations in pipeline, and it makes a lot of sense in the domain I'm modeling since its main focus are data structure traversals and pipelines of transformations applied to a source.</p>
  
  <p>I fell in love with the conciseness (I am a huge fan of the pipeline (|>) operator) and power of F# and am looking for some convenient syntax that makes a bunch of chaining operations looks simple and explicit in the necessity for logging certain actions along the chain.... soooo here is what I encounter so far and really need some guidance:</p>
  
  <ol>
  <li>Quotations</li>
  <li>Type Extensions</li>
  <li>Quotations 2nd Thoughts</li>
  <li>Conclusions and Help</li>
  </ol>
  
  <p>I am really really newbie, so if you think that I'm missing something stupid and completely obvious, please don't hesitate to let me know, what I did is probably completely wrong xD. Without further ado, here is the starting code that I wanted to decorate</p>
  
  <pre class="lang-ml prettyprint-override"><code>type DSError =
      ....
  type DataStructure =
      ...
  
  module DataStructure =
      let root : 'node =
          ...
      let firstChild (node:'node) (data: DataStructure) : Result&lt;'node,DSError&gt; =
          ...
      let nextSibling (node:'node) (data: DataStructure) =
          ...
  
  module Operators =
      let inline ( @&gt; ) data node = (Ok node, data)
      let inline ( &gt;&gt;= ) (result, data) func =
          match result with
          | Error err -&gt; Error err, data
          | Ok res -&gt; func res data, data
  
  module TraverseExamples =
      open Operators
  
      let arbitraryTraverse (data: DataStructure) =
          data @&gt; root
          &gt;&gt;= DataStructure.firstChild
          &gt;&gt;= DataStructure.nextSibling
          &gt;&gt;= DataStructure.firstChild
  </code></pre>
  
  <p>I was looking to produce something like this, where <code>&gt;&gt;=!</code> is the log decorated form of <code>&gt;&gt;=</code> :</p>
  
  <pre class="lang-ml prettyprint-override"><code>data @&gt; root
  &gt;&gt;=! DataStructure.firstChild    // This function will log
  &gt;&gt;= DataStructure.nextSibling    // This won't
  
  // executed: DataStructure.firstChild
  // arguments: Ok root, [/some inmutable data structure/]
  // result: Ok firstChildOfRoot, [/some inmutable data structure/]
  </code></pre>
  
  <p>So the only piece that I don't know was how to get the name and module of a function passed as an argument.</p>
  
  <hr>
  
  <h2>1. Quotations</h2>
  
  <p>The first thing I found was about quotations.</p>
  
  <ul>
  <li><a href="https://stackoverflow.com/questions/29599456/how-to-get-the-name-of-function-argument-in-f">How to get the name of function argument in F#?</a></li>
  <li><a href="https://stackoverflow.com/questions/4604139/how-to-get-the-f-name-of-a-module-function-etc-from-quoted-expression-match">How to Get the F# Name of a Module, Function, etc. From Quoted Expression Match</a></li>
  </ul>
  
  <p>From the first one (some replies under the accepted answer), I get to know that not only quotations are the way to go for extracting this type of information but also that it can be automatically cast from normal functions as arguments using the <code>[&lt;ReflectedDefinition&gt;]</code> attribute. From the second one, I get a form of obtaining the correct FSharp name. Here is what I tried:</p>
  
  <pre class="lang-ml prettyprint-override"><code>let inline ( &gt;&gt;=! ) (result, data) [&lt;ReflectedDefinition&gt;]func =
  //Unexpected symbol '[&lt;' in binding
  </code></pre>
  
  <p>But <code>[&lt;ReflectedDefinition&gt;]</code> and attribute sin general appears to work only with static members. So I tried the static member approach using a discriminated union for recognition of the operators:</p>
  
  <pre class="lang-ml prettyprint-override"><code>type Logger&lt;'T&gt; =
          | LogResult of ('T)
  
          static member bind(LogResult tuple, [&lt;ReflectedDefinition&gt;]func:Expr&lt;_-&gt;_&gt;) = 
              match func with
              | DerivedPatterns.Lambdas(_, Patterns.Call(_,methodInfo,_)) -&gt;
                  printfn "%s" methodInfo.Name
              | Patterns.ValueWithName(_, _, data) -&gt; printfn "%s" data
              | _ -&gt; printfn "%s" "invalid"
  
          static member ( &gt;&gt;=! ) (LogResult tuple, [&lt;ReflectedDefinition&gt;]func:Expr&lt;_-&gt;_&gt;) = 
              match func with
              | DerivedPatterns.Lambdas(_, Patterns.Call(_,methodInfo,_)) -&gt;
                  printfn "%s" methodInfo.Name
              | Patterns.ValueWithName(_, _, data) -&gt; printfn "%s" data
              | _ -&gt; printfn "%s" "invalid"
  
  // Prefix form worked as expected. Both print firstChild
  Logger.bind(LogResult (data, root), DataStructure.firstChild)
  (&gt;&gt;=!)(LogResult (data, root), DataStructure.firstChild)
  
  // This doesnt work: 
  //    type constrain mismatch 'a -&gt; 'b -&gt; Result&lt;'a,'c&gt; 
  //    is not compatible with Expr&lt;'a -&gt; 'b&gt;
  LogResult (data, root) &gt;&gt;=! DataStructure.firstChild
  </code></pre>
  
  <p>I thought that it was my fault that both parameters weren't from type Logger (its something expected that an infix static operation works with the same type) so I change the method a little bit just for testing my assumptions. Supposing I have an eval function for quotations (like the one from LINQ or Unquote) called <code>quotationEval</code> I could do the next:</p>
  
  <pre class="lang-ml prettyprint-override"><code>type Logger&lt;'T,'U&gt; =
      | LogResult of ('T * 'U)
      | LogFunc of ('T -&gt; 'U -&gt; 'T)
      ...
      ...
      static member ( &gt;&gt;=! ) (LogResult tuple, [&lt;ReflectedDefinition&gt;]logFunc) = 
              let logFuncUnquoted = quotationEval(logFunc)
              match logFuncUnquoted with
              | LogFunc func -&gt;
                  match &lt;@ func @&gt; with
                  | DerivedPatterns.Lambdas(_, Patterns.Call(_,methodInfo,_)) -&gt;
                      printfn "%s" methodInfo.Name
                  | Patterns.ValueWithName(_, _, data) -&gt; printfn "%s" data
                  | _ -&gt; printfn "%s" "invalid"
              | _ -&gt; printfn "%s" "more invalid"
  
  // This doesnt work either: 
  //    type constrain mismatch Logger&lt;'a,'b&gt; 
  //    is not compatible with Expr&lt;Logger&lt;'a,'b&gt;&gt;
  LogResult (data, root) &gt;&gt;=! LogResult DataStructure.firstChild
  </code></pre>
  
  <p>It seems that the first example was okay, and the problem instead was with infix operators. I really wanted to use infix notation instead of prefixed named functions for composition but what if I used these functions from within a let bounded <code>&gt;&gt;=!</code>, changing one of the functions from Logger:</p>
  
  <pre class="lang-ml prettyprint-override"><code>type Logger&lt;'T&gt; =
      ...
      static member logFunc([&lt;ReflectedDefinition&gt;]func:Expr&lt;_-&gt;_&gt;) = 
              match func with
              | DerivedPatterns.Lambdas(_, Patterns.Call(_,methodInfo,_)) -&gt;
                  printfn "The function called was: %s" methodInfo.Name
              | Patterns.ValueWithName(_, _, data) -&gt; printfn "%s" data
              | _ -&gt; printfn "%s" "invalid"
  
  let inline ( &gt;&gt;=! ) (result, data) func =
      match result with
      | Error err -&gt; Error err, data
      | Ok res -&gt;
          Logger.logFunc func 
          func res data, data
  
  data @&gt; root
  &gt;&gt;=! DataStructure.firstChild
  // The function called was: func
  </code></pre>
  
  <p>Okay no, that doesn't do the trick either. And in the example above this, where I do <code>match &lt;@ func @&gt; with</code> the result would suffer the same problem in case it worked. I need to directly pass the function to the one with <code>[&lt;ReflectedDefinition&gt;]</code> because if I don't do so, the name of the function is taken from the argument. Using again the eval function described earlier <code>quotationEval</code> I could do the next:</p>
  
  <pre class="lang-ml prettyprint-override"><code>let inline ( &gt;&gt;=! ) (result, data) func =
      match result with
      | Error err -&gt; Error err, data
      | Ok res -&gt;
          Logger.logFunc func
          let f = quotationEval func 
          f res data, data
  
  data @&gt; root
  &gt;&gt;=! &lt;@ DataStructure.firstChild @&gt;
  </code></pre>
  
  <p>But I think that the <code>&lt;@ ... @&gt;</code> syntax is rather arbitrary and has nothing to do with logging except as a convenient hack for this situation so I think that maybe... I could extend functions (extensions are a static member so it may in principle accept the <code>[&lt;ReflectedDefinition&gt;]</code> attribute) and letting this hack not visible in the API.</p>
  
  <hr>
  
  <h2>2. Type Extensions</h2>
  
  <p>I specifically looked for extending the function type so this was what I found:</p>
  
  <ul>
  <li><a href="https://docs.microsoft.com/es-es/dotnet/fsharp/language-reference/type-extensions" rel="nofollow noreferrer">https://docs.microsoft.com/es-es/dotnet/fsharp/language-reference/type-extensions</a></li>
  <li><a href="https://stackoverflow.com/questions/23292379/extension-method-with-f-function-type">Extension method with F# function type</a></li>
  <li><a href="https://stackoverflow.com/questions/25642150/overloading-operators-in-type-extensions">Overloading operators in type extensions</a></li>
  </ul>
  
  <p>In this case, since I needed both functions, the first tuple is a constant function that given a unit returns the tuple. Also, I only code the chaining execution of the tuple with the first function, my goal was only to know if infix operators work in type extensions or not:</p>
  
  <pre class="lang-ml prettyprint-override"><code>[&lt;Extension&gt;]
      type FunctionExtension() =
          [&lt;Extension&gt;]
          static member inline ( &gt;&gt;=! ) (f: unit -&gt; 'a*'b) (g: 'a -&gt; 'b -&gt; 'c) = 
              (fun (x, y) -&gt; g x y) (f())
          [&lt;Extension&gt;]
          static member inline bind(f: unit -&gt; 'a*'b, g: 'a -&gt; 'b -&gt; 'c) =
              (fun (x, y) -&gt; g x y) (f())
  
  let init = (fun () -&gt; (root, data))
  
  // Prefix form worked as expected. Both execute
  init.bind DataStructure.firstChild
  (&gt;&gt;=!)(init, DataStructure.firstChild)
  
  // This doesnt work: 
      //    expecting a type supporting the operation &gt;&gt;=!
  init &gt;&gt;=! DataStructure.firstChild
  </code></pre>
  
  <p>In this case, it doesn't even work ( and I haven't defined g as an Expr&lt;<em>-></em>>), the infix operator was never recognized. In the previous examples, the problem was in types, not recognition. Reading through the answer in the third link (<a href="https://stackoverflow.com/questions/25642150/overloading-operators-in-type-extensions">Overloading operators in type extensions</a>) it appears that I'll need some struggling to let infix operators work in type extensions but given that it has an intermediary let bounded function in that explanation, the whole point for abstracting meta-data would never work as in my previous examples.</p>
  
  <p>That was fast... I came back then to Quotations using a different approach</p>
  
  <hr>
  
  <h2>3. Quotations 2nd Thoughts</h2>
  
  <p>Almost 2 working days have passed since I started to investigate and tried different things and I'm almost to give up when I came to think in a different approach. It uses almost the same things used in the first section but not at the chaining functions but as actual "decorators", maybe we could get to something like this:</p>
  
  <pre class="lang-ml prettyprint-override"><code>data @&gt; root
  &gt;&gt;= log DataStructure.firstChild
  &gt;&gt;= DataStructure.nextSibling
  &gt;&gt;= log DataStructure.firstChild
  </code></pre>
  
  <p>Where log makes the heavy work of getting the function metadata and it only applies whenever I think it's needed. It looks succinct, simple and explicit, could I achieve something like that with what I learn? I think I could, because I'm not struggling with infix operators anymore. There are 2 important functions not defined so here is my try:</p>
  
  <pre class="lang-ml prettyprint-override"><code>let logger = MyFavoriteLoggingFramework.Create()
  
  let private funcData (expr: Expr&lt;_-&gt;_&gt;) =
      // return a composition of [Module] and [FunctionName]
      // implemantations is similar to the match in the first Logger.bind
      // with slightly more complexity for the generated string
  
  type Log&lt;'T&gt; = 
          | LogResult of ('T)
  
          static member startAt(data, initial) = 
              logger.debug("")
              logger.debug("logger sequence started")
              LogResult &lt;| (Ok initial, data)
  
          static member debug([&lt;ReflectedDefinition&gt;]func:Expr&lt;_-&gt;_&gt;) =
              logger.debug("")
              logger.debug(funcData func)
              (true, (quotationEval func))
  
          static member (&gt;&gt;=) (LogResult (result, data), (_, expr:'a-&gt;'b-&gt;Result&lt;'a,'a0&gt;)) =
              match result with
              | Ok res -&gt; 
                  logger.debug(sprintf "\t%s: %A" "arguments" (result, data))
                  let ret = expr res data, data
                  logger.debug(sprintf "\t%s: %A" "return" ret)
                  LogResult &lt;| (ret)
              | Error err -&gt; 
                  logger { debug (sprintf "\t%s: %A" "previous error" err)}
                  LogResult &lt;| (Error err, data)
  
          static member (&gt;&gt;=) (LogResult (result, data), expr:'a-&gt;'b-&gt;Result&lt;'a,'a0&gt;) =
              match result with
              | Ok res -&gt; LogResult &lt;| (expr res data, data)
              | Error err -&gt; LogResult &lt;| (Error err, data)
  
  data.startAt root
  &gt;&gt;= Logger.debug DataStructure.firstChild
  &gt;&gt;= Logger.debug DataStructure.nextSibling
  &gt;&gt;= DataStructure.firstChild
  
  //
  //logger sequence started
  //
  //    executed: DataStructure.firstChild
  //    arguments: Ok root, [/some inmutable data structure/]
  //    return: Ok firstChildRoot, [/some inmutable data structure/]
  //
  //    executed: DataStructure.nextSibling
  //    arguments: Ok firstChildRoot, [/some inmutable data structure/]
  //    return: Ok secondChildRoot, [/some inmutable data structure/]
  </code></pre>
  
  <p>As you could see, there are two <code>&gt;&gt;=</code> functions, one that takes a tuple of bool and expr as the second argument and one that takes only a function. The only way to have a tuple instead of a function is passing first through Logger.debug so Only when using Logger. debug the arguments and results gets printed. its a bit more verbose than what I want but is explicit, and I prefer it over the <code>&lt;@ ... @&gt;</code> syntax around every function to log.</p>
  
  <hr>
  
  <h2>4. Conclusions and Help</h2>
  
  <p>Well if you are here, I want to thank you, I know it's pretty large but that's the only way to explain the succession of what I tried and what finally works. I didn't have the time yet to clean the code but I think I might do it tomorrow and upload a minimal cleaned version of the final one to a gist. I want to hear about things that I've missed, feedback and knowing if there are better, more clear or idiomatic ways to do this, especially leveraging infix operators (i don't quite understand why I can't make them work in this situations, I'm really feel struggling with the language here) I'd love to write something like</p>
  
  <pre class="lang-ml prettyprint-override"><code>data @&gt; root
  &gt;&gt;=! DataStructure.firstChild
  &gt;&gt;=! DataStructure.nextSibling
  &gt;&gt;= DataStructure.firstChild
  
  // or like
  
  data @&gt; root
  &gt;&gt;= log DataStructure.firstChild
  &gt;&gt;= log DataStructure.nextSibling
  &gt;&gt;= DataStructure.firstChild
  </code></pre>
  
  <p>Can't get any of this, the first because of infix operator not working as I imagined and the second because of this:</p>
  
  <pre class="lang-ml prettyprint-override"><code>let log = Logger.debug
  
  data.init root
  &gt;&gt;= log DataStructure.firstChild
  &gt;&gt;= DataStructure.nextSibling
  &gt;&gt;= DataStructure.firstChild
  
  //
  //logger sequence started
  //
  //    executed: _arg0
  //    arguments: Ok root, [/some inmutable data structure/]
  //    return: Ok firstChildRoot, [/some inmutable data structure/]
  </code></pre>
  
  <p>Because of not directly passing the parameter to the function marked with the automatic quotation attribute.</p>
  
  <p>I'm probably missing something really obvious so if that's the case please enlighten me, I really love what I'm doing so far and F# is a really beautiful language. Thanks to all and I wait for your comments; and again, sorry for my English ^^.</p>
  
  <hr>
  
  <h2>EDIT 1</h2>
  
  <p><strong>Here is a gist of the polished last version:</strong> 
  <a href="https://gist.github.com/rodrigo-o/1ef435887d3419be0272a5afe810f8c6" rel="nofollow noreferrer">https://gist.github.com/rodrigo-o/1ef435887d3419be0272a5afe810f8c6</a></p>