Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Monad - a functional design pattern

148 views

Published on

Discusses how Monad can be used to refactor existing Java/C# code

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Monad - a functional design pattern

  1. 1. Refactoring using Functional Design Patterns Mårten Rånge/Atomize AB
  2. 2. A("capabilityIdentity", Scalar, Iwd(2))
  3. 3. A("txPortMaximumOutputPower", P(dBm0_1, dBm0_1) , ProdDataXml("/board/powerClassUsage")) A("txPortMaximumPar" , P(dBm0_1, dBm0_1) , SysDataParam("capMaxPar"))
  4. 4. A("txOperationBandLowEdge" , F(kHz, kHz), Gpp3("bandLimits",freqClassUsage).Then(Select(0))) A("txOperationBandHighEdge", F(kHz, kHz), Gpp3("bandLimits",freqClassUsage).Then(Select(1)))
  5. 5. A("capabilityPortArray", Unspecified, CapabilityPortArray)
  6. 6. String (obviously) Enum Enum What type is this? A("txOperationBandLowEdge" , F(kHz, kHz), Gpp3("bandLimits",freqClassUsage).Then(Select(0))) A("txOperationBandHighEdge", F(kHz, kHz), Gpp3("bandLimits",freqClassUsage).Then(Select(1)))
  7. 7. Func<string>
  8. 8. Func<U> Then<T, U>(this Func<T> t, Func<T, U> u) { return () => u (t ()); }
  9. 9. Func<string> Gpp3(string path, string id)
  10. 10. Func<string, string> Select(int idx)
  11. 11. Gpp3("bandLimits",freqClassUsage).Then(Select(0))
  12. 12. String (obviously) Enum Enum Func<string> A("txOperationBandLowEdge" , F(kHz, kHz), Gpp3("bandLimits",freqClassUsage).Then(Select(0))) A("txOperationBandHighEdge", F(kHz, kHz), Gpp3("bandLimits",freqClassUsage).Then(Select(1)))
  13. 13. Perfect?
  14. 14. Func<string> Gpp3(string path, string key) { return () => QueryContext.Instance.Gpp3Data.Get (path, key); }
  15. 15. Func<QueryContext, T>
  16. 16. // When composing we lose the Context Func<QueryContext, U> Then<T, U>( this Func<QueryContext, T> t , Func<T, U> u) { return ctx => u(t (ctx)); }
  17. 17. Down the rabbit hole...
  18. 18. type AttributeQuery<'T> = unit -> 'T
  19. 19. type AttributeQuery<'T> = QueryContext -> 'T
  20. 20. val gpp3: string -> string -> AttributeQuery<string> val prodDataXml: string -> AttributeQuery<string> val select: int -> string -> AttributeQuery<string>
  21. 21. // type AttributeQuery<'T> = QueryContext -> 'T let gpp3 path key = fun ctx -> ctx.Gpp3Data.Get path key
  22. 22. // type AttributeQuery<'T> = QueryContext -> 'T let select idx s = fun ctx -> let vs = s.Split ',' vs.[idx] // TODO: error handling
  23. 23. //Gpp3("bandLimits",freqClassUsage).Then(Select(0)) gpp3 "bandLimits" freqClassUsage ??? select 0
  24. 24. val Bind: AttributeQuery<'T> -> ('T -> AttributeQuery<'U>) -> AttributeQuery<'U> val Return: 'T -> AttributeQuery<'T>
  25. 25. // type AttributeQuery<'T> = QueryContext -> 'T let Return v = fun ctx -> v
  26. 26. // type AttributeQuery<'T> = QueryContext -> 'T let Bind firstq fsecondq = fun ctx -> let first = firstq ctx let secondq = fsecondq first let second = secondq ctx second
  27. 27. let (>>=) firstq fsecondq = Bind firstq fsecondq
  28. 28. //Gpp3("bandLimits",freqClassUsage).Then(Select(0)) gpp3 "bandLimits" freqClassUsage >>= select 0
  29. 29. let bandLimits : AttributeQuery<string> = gpp3 "bandLimits" freqClassUsage
  30. 30. let hello : AttributeQuery<string> = select 0 "Hello,There"
  31. 31. let select0 : string -> AttributeQuery<string> = select 0 // "Hello,There"
  32. 32. let q : AttributeQuery<string> = bandLimits >>= select0
  33. 33. val Bind: AttributeQuery<'T> // bandlimits -> ('T -> AttributeQuery<'U>) // select0 -> AttributeQuery<'U> val Return: 'T -> AttributeQuery<'T>
  34. 34. // type AttributeQuery<'T> = QueryContext -> 'T let Bind firstq fsecondq = fun ctx -> let first = firstq ctx // bandlimits ctx let secondq = fsecondq first // select0 first let second = secondq ctx second
  35. 35. //Gpp3("bandLimits",freqClassUsage).Then(Select(0)) gpp3 "bandLimits" freqClassUsage >>= select 0
  36. 36. Back to Kansas...
  37. 37. delegate T AttributeQuery<T> (QueryContext ctx);
  38. 38. AttributeQuery<T> Return<T> (T v) { return ctx => v; }
  39. 39. AttributeQuery<U> Bind<T, U> ( this AttributeQuery<T> firstq , Func<T, AttributeQuery<U>> fsecondq) { return ctx => { var first = firstq (ctx); var secondq = fsecondq (first); var second = secondq (ctx); return second; }; }
  40. 40. public AttributeQuery<String> Gpp3(string path, string key); public AttributeQuery<String> ProdDataXml(string path); public Func<string, AttributeQuery<string>> Select(int idx);
  41. 41. Gpp3("bandLimits",freqClassUsage).Then(Select(0))
  42. 42. Gpp3("bandLimits",freqClassUsage).Bind(Select(0))
  43. 43. String (obviously) Enum Enum AttributeQuery<string> A("txOperationBandLowEdge" , F(kHz, kHz), Gpp3("bandLimits",freqClassUsage).Bind(Select(0))) A("txOperationBandHighEdge", F(kHz, kHz), Gpp3("bandLimits",freqClassUsage).Bind(Select(1)))
  44. 44. type AttributeQuery<'T> = QueryContext -> 'T val Bind: AttributeQuery<'T> -> ('T -> AttributeQuery<'U>) -> AttributeQuery<'U> val Return: 'T -> AttributeQuery<'T>
  45. 45. Monad
  46. 46. “A monad is a monoid in the category of endofunctors, what's the problem?” Philip Wadler (Fake but funny)
  47. 47. // Monad type class // https://wiki.haskell.org/Monad type M<'T> val Bind : M<'T> -> ('T -> M<'U>) -> M<'U> val Return: 'T -> M<'T>
  48. 48. // Monad laws // https://wiki.haskell.org/Monad_laws let (>=>) t u = fun v -> Bind (t v) u Left identity : Return >=> g ≡ g Right identity: f >=> Return ≡ f Associativity : (f >=> g) >=> h ≡ f >=> (g >=> h)
  49. 49. Left identity : x + 0 ≡ x Right identity: 0 + x ≡ x Associativity : (x + y) + z ≡ x + (y + z)
  50. 50. The Essence of Monad ”The essence of monad is thus separation of composition timeline from the composed computation's execution timeline, as well as the ability of computation to implicitly carry extra data, as pertaining to the computation itself, in addition to its one (hence the name) output, that it will produce when run (or queried, or called upon).“ https://wiki.haskell.org/Monad
  51. 51. Monads are useful  We like to define a query to an attribute  Query implies separation between composition and execution  We don’t want to our query to rely on singletons  Makes testing and composition (if effectful) difficult  No singletons implies an extra data  This is the essence of Monads
  52. 52. Experimentation leads to understanding
  53. 53. Common usages for Monads  Coroutines  Environment state  Parsers  Rules  Queries  Tracing  Transformers
  54. 54. https://github.com/mrange/presentations/ fsharp/ce/turtle
  55. 55. http://www.slideshare.net/martenrange/ monad-a-functional-design-pattern Questions?

×