{"id":326,"date":"2009-11-17T02:05:39","date_gmt":"2009-11-17T01:05:39","guid":{"rendered":"http:\/\/www.nobugs.org\/blog\/?p=326"},"modified":"2009-11-17T02:23:04","modified_gmt":"2009-11-17T01:23:04","slug":"technical-debt-or-mortgages-in-haskell","status":"publish","type":"post","link":"https:\/\/www.nobugs.org\/blog\/archives\/2009\/11\/17\/technical-debt-or-mortgages-in-haskell\/","title":{"rendered":"Technical debt (or, mortgages in Haskell)"},"content":{"rendered":"<p>I recently got fed up trying to understand my mortgage using excel.  After twenty minutes guddling with cells and individual values, I felt the need to create higher-level abstractions such as &#8220;mortgage&#8221; and &#8220;payment strategy&#8221;.  I also wanted to create a list of possible repayment strategies and easily compare them to see how it affects the loan duration and total interest payed.  This is possible in excel, but no fun.<\/p>\n<p>So, fast-forward to the end of an evening&#8217;s hacking with Haskell. I now have <a href=\"http:\/\/www.nobugs.org\/developer\/hmortgage\/Mortgage.hs\">hmortgage<\/a>, a EDSL for expressing payment strategies and code which will expand out a mortgage into monthly steps, like this:<\/p>\n<pre>\r\nWe are looking at loan of \u00a31000.00 at 5.0% over 10y, which has required monthly payment of \u00a310.58\r\nBaseline:\r\n        Total interest: \u00a3272.97 Total payments: \u00a31272.97 Duration=10y 1m\r\nOverpayment scenario \"2 pm, 200 initial\":\r\n        Total interest: \u00a3132.09 Total payments: \u00a31132.09 Duration=6y 3m\r\n        Compared to baseline: interest=\u00a3-140.88, payments=\u00a3-140.88, duration=-3y 10m\r\nFor month 1, balance: \u00a31000.00 -> \u00a3791.58       (interest: \u00a34.16, payment: \u00a3212.58)\r\nFor month 2, balance: \u00a3791.58 -> \u00a3782.29        (interest: \u00a33.29, payment: \u00a312.58)\r\nFor month 3, balance: \u00a3782.29 -> \u00a3772.96        (interest: \u00a33.25, payment: \u00a312.58)\r\nFor month 4, balance: \u00a3772.96 -> \u00a3763.60        (interest: \u00a33.22, payment: \u00a312.58)\r\n<\/pre>\n<p>ie. if you overpay by \u00a32 each month, and pay an initial lump sum of \u00a3200, you&#8217;ll save about \u00a3140 overall and will repay the mortgage nearly 4 years early.<\/p>\n<p>There&#8217;s a few points of haskelly interest in this code, mostly inspired by stuff I read a few years ago &#8211; behaviors in FRP, and SPJ&#8217;s &#8220;composing contracts&#8221; paper.<\/p>\n<h3>Combinators for payment strategies<\/h3>\n<p>I have a few primitive payment strategies, which can be combined into more complex strategies:<\/p>\n<ul>\n<li>monthlyPaymentsOf (100 Pounds)\n<\/li>\n<li>lumpSumOf (100 Pounds)\n<\/li>\n<li>lumpSumOf (100 Pounds) `after` (1 Year)\n<\/li>\n<li>monthlyPaymentsOf (100 Pound) +. (lumpSumOf (100 Pounds) `after` (1 Year))\n<\/li>\n<\/ul>\n<h3>Shallow embedding of DSL<\/h3>\n<p>The dsl is a shallow embedding; it represents the monthly payment plan as a function from month-number to the payment amount, ie. Integer -> Currency.  There&#8217;s a problem with this approach &#8211; the only thing you can do with a function is apply it to some arguments.  This is fine for finding the payment for a particular month, but I would also like to derive a textual description of the payment plan &#8211; which isn&#8217;t possible with functions.<\/p>\n<p>From stuff I&#8217;ve read previously, I think my two options are:<\/p>\n<ol>\n<li>Lisp-like: Represent the payment schedule as data (ie. like an AST) and provide an eval function.  This allows introspection into structure of the payment schedule.  Code is data, data is code.\n<\/li>\n<li>Arrow-like: The payment strategy could be a tuple of the function and a textual description.  When strategies are combined, the combinator would merge the textual descriptions as well as producing new combined functions.  I&#8217;m not totally convinced that the english language is &#8216;compositional&#8217; in this way though &#8211; it might end up with really clumsy phrasing.\n<\/li>\n<\/ol>\n<h3>Crazy Lennart-inspired postfix operators<\/h3>\n<p>Initially, the only way I had to create a &#8216;Currency&#8217; value was via the &#8216;pounds&#8217; function.  In haskell, the function precedes the argument, hence it looks like &#8220;pounds 20&#8221;.  The source code would read nicer if I could write this as &#8220;20 pounds&#8221; like we do in english.  I didn&#8217;t think this was possible in Haskell.<\/p>\n<p>Then I remembered seeing Lennart Augustsson&#8217;s crazy embedding of <a href=\"http:\/\/hackage.haskell.org\/package\/BASIC\">BASIC into Haskell<\/a>.  In particular, he had code which looked like this:<\/p>\n<pre lang=\"haskell\">\r\nrunBasic $ do\r\n  10 PRINT \"HELLO\"\r\n  20 END\r\n<\/pre>\n<p>How the heck does that parse?  It&#8217;s using &#8216;do&#8217; notation, so &#8220;20 END&#8221; must have a type in the Monad class.  But, as I understood things, &#8220;x y&#8221; means &#8220;apply the (function) value x to value y&#8221;.  And &#8220;20&#8221; doesn&#8217;t look much like a function to me.<\/p>\n<p>Digging into the source, I found this:<\/p>\n<pre lang=\"haskell\">\r\n-- 10 END\r\ninstance Num (END -> Expr a) where\r\n    fromInteger i c = ...\r\n<\/pre>\n<p>Hmm, interesting.  This is saying that (some) function type can be treated as if it is &#8220;number like&#8221; and provides a mechanism for converting integer literals in source code to that type.  I hadn&#8217;t fully appreciated this, but the Haskell Report <a href=\"http:\/\/www.haskell.org\/onlinereport\/basic.html#numeric-literals\">says<\/a> that numeric literals aren&#8217;t quite as literal as I expected &#8211; the literal integer value gets passed through &#8216;fromInteger&#8217; and can therefore be made into any Numeric type.<\/p>\n<p>So this code really says &#8220;Hey ghc, if you come across a &#8220;42&#8221; in the source code, you can turn that into a function if you need to&#8221;.  In the BASIC example, the next thing on line 20 is &#8220;END&#8221;, a constructor for the type also called END.  So, ghc will be looking to turn &#8220;42&#8221; into something that can be used as a function taking an argument of type END, and so it&#8217;ll call this instance of fromInteger.<\/p>\n<p>Hurrah, I can use the same &#8216;trick&#8217; to make my currencies look nicer:<\/p>\n<pre lang=\"haskell\">\r\ndata MONEY = Pounds | Pence\r\n\r\ninstance Num (MONEY -> Currency) where\r\n  fromInteger i Pounds = C (i * 100)\r\n  fromInteger i Pence = C i\r\n<\/pre>\n<p>Now I can say &#8220;42 Pounds&#8221; or &#8220;23 Pence&#8221;.  The &#8220;42&#8221; will become a function with type MONEY -> Currency.  The &#8220;MONEY&#8221; type is really just a tag &#8211; used to choose the parse but that&#8217;s it.  The Pounds\/Pence tags force the appropriate overloading of fromInteger to be chosen, and this will construct a Currency value (represented as number of pence, and using a simple wrapper constructor called C).<\/p>\n<p>Is this better, or just &#8220;clever&#8221;?  I&#8217;m not sure yet.  It&#8217;s certainly easier to read.  But I feel I&#8217;ve taken a step away from &#8220;pure haskell&#8221; into a slightly weird world.  Still, if I were writing in lisp, I wouldn&#8217;t think twice about doing this kind of thing.<\/p>\n<h3>The actual app<\/h3>\n<p>Shocker, I&#8217;ve produced an app which is actually useful to me in &#8220;teh real world&#8221;.   I have a big TODO list of stuff which will fit nicely into the app &#8211; time-varying interest rates, inflation predictions and NPV calculations.  None of  which, of course, I will ever actually get around to adding.  But it&#8217;s still useful in its present state, so a win!<\/p>\n<p>Here&#8217;s what the &#8220;summary&#8221; view says &#8211; it omits the montly breakdown and instead reports the overall savings possible via the different payment strategies:<\/p>\n<pre>\r\nWe are looking at loan of \u00a31000.00 at 5.0% over 10y, which has required monthly payment of \u00a310.58\r\nBaseline:\r\n        Total interest: \u00a3272.97 Total payments: \u00a31272.97 Duration=10y 1m\r\nOverpayment scenario \"2 pm, 200 initial\":\r\n        Total interest: \u00a3132.09 Total payments: \u00a31132.09 Duration=6y 3m\r\n        Compared to baseline: interest=\u00a3-140.88, payments=\u00a3-140.88, duration=-3y 10m\r\nOverpayment scenario \"2 pm only\":\r\n        Total interest: \u00a3216.50 Total payments: \u00a31216.50 Duration=8y 1m\r\n        Compared to baseline: interest=\u00a3-56.47, payments=\u00a3-56.47, duration=-2y\r\nOverpayment scenario \"200 initial\":\r\n        Total interest: \u00a3163.52 Total payments: \u00a31163.52 Duration=7y 8m\r\n        Compared to baseline: interest=\u00a3-109.45, payments=\u00a3-109.45, duration=-2y 5m\r\nOverpayment scenario \"400 initial\":\r\n        Total interest: \u00a387.73 Total payments: \u00a31087.73 Duration=5y 6m\r\n        Compared to baseline: interest=\u00a3-185.24, payments=\u00a3-185.24, duration=-4y 7m\r\nOverpayment scenario \"200 after 2y\":\r\n        Total interest: \u00a3191.42 Total payments: \u00a31191.42 Duration=7y 10m\r\n        Compared to baseline: interest=\u00a3-81.55, payments=\u00a3-81.55, duration=-2y 3m\r\nOverpayment scenario \"400 after 2y\":\r\n        Total interest: \u00a3137.90 Total payments: \u00a31137.90 Duration=5y 10m\r\n        Compared to baseline: interest=\u00a3-135.07, payments=\u00a3-135.07, duration=-4y 3m\r\n<\/pre>\n<p>Eep, it&#8217;s 01:30 .. how did that happen?  Stoopid jetlag &#8230;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I recently got fed up trying to understand my mortgage using excel. After twenty minutes guddling with cells and individual values, I felt the need to create higher-level abstractions such as &#8220;mortgage&#8221; and &#8220;payment strategy&#8221;. I also wanted to create a list of possible repayment strategies and easily compare them to see how it affects [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[9],"class_list":["post-326","post","type-post","status-publish","format-standard","hentry","category-programming","tag-haskell"],"_links":{"self":[{"href":"https:\/\/www.nobugs.org\/blog\/wp-json\/wp\/v2\/posts\/326","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.nobugs.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.nobugs.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.nobugs.org\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.nobugs.org\/blog\/wp-json\/wp\/v2\/comments?post=326"}],"version-history":[{"count":18,"href":"https:\/\/www.nobugs.org\/blog\/wp-json\/wp\/v2\/posts\/326\/revisions"}],"predecessor-version":[{"id":344,"href":"https:\/\/www.nobugs.org\/blog\/wp-json\/wp\/v2\/posts\/326\/revisions\/344"}],"wp:attachment":[{"href":"https:\/\/www.nobugs.org\/blog\/wp-json\/wp\/v2\/media?parent=326"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.nobugs.org\/blog\/wp-json\/wp\/v2\/categories?post=326"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.nobugs.org\/blog\/wp-json\/wp\/v2\/tags?post=326"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}