Without a deeper understanding of your domain it's hard for me to offer much advice. One thing you definitely should check out (and probably use) is discriminated unions, they sound like they may come in handy. See e.g.
[link:lorgonblog.spaces.live.com]
and the discussion of the 'HandValuation' type here:
[link:lorgonblog.spaces.live.com]
I'm thinking e.g. about
1 2 3
type ExoticWager = | Double of int * int * money | Treble of int * int * int * money
You may also check out
[link:lorgonblog.spaces.live.com]
for general thoughts about OOP versus FP.
Discriminated Unions look pretty good. I guess my only reservation is that I have a kind of mental block about wager amount and combination being stored in the same tuple.
One reason for this is that sometimes I will wish to sort lists of wagers by lexicographic ascending runner combination, e.g.:
2/7/12 - $100.00
6/1/1 - $5.00
14/14/9 - $99.00
and sometimes by ascending wager amount
6/1/1 - $5.00
14/14/9 - $99.00
2/7/12 - $100.00
Presumably less confusing and done more elegantly if combinations and amounts are two separate items in some kind of structure or object?
OTOH I do like very much the fact that DUs get one lexicographic sort order for free.
Clearly I need to do more reading and some experimentation over the coming weekend, but thanks very much for your tips!
When reading the description of your problem I was reminded of the "Composing Contracts" paper by Peyton-Jones/Eber/Sewar [1]. This paper describes a DSL for describing derivative contracts, which are not so different from the bets you describe. Creating an abstract description of a problem, often using union types to form, at an AST like structure, then interpreting them or transforming them is a common technique in FP and I believe it would work well in this case.
Having said that I don't believe you need to throw away you OO techniques entirely, one the nice things about F# is the way you can add members to its native record and union types to get an OO like feel where appropriate.
Cheers,
Rob
Thanks for reminding me of this paper! I'd squirreled away the book chapter version of it in my 'Learn Haskell One Rainy Day' Folder and promptly forgotten about it. One reason I'd grabbed it originally is that I've had the idea for some time that we could certainly benefit from a high level approach to various automated position taking approaches in some of the online markets we trade in (serious 'gambling' has a lot of similarities to the the 'real' world of quants). But that's a problem for another day when I've got my head around FP a lot more.
I'm not sure (speaking from the depths of ignorance) that combinators are quite the thing for designing the simple compound types I outlined above.... BUT - there was one issue I did not mention which gives rise to headaches when done in C# & co... - which is that it would be nice at design time to be able to declaratively spell out some other constraints on permissible data. e.g. it's clear that a Treble runner combination is int * int * int - but I would also like (in Market A) to be able to limit each tuple position value to be in range 1 through 14, and in (Market B) to limit each tuple position value to be in range 1 through 20. The more generally and succinctly I can define such run-time validation checking at design time, the easier it will be to quickly implement new wager types without excessive code duplication.
I can imagine that I ought to be able to specify a wager type as a combination with associated constraint checker function, and an amount with associated constraint checker function.
Another way of saying this is that Trebles are structurally the same everywhere, but races in (say) Hong Kong have a different max number of runners in a field cf. (say) UK races. Similarly wager amounts in HK have different minimum unit amount and different permissible discrete increments than wager amounts in the UK. So it seems to me like I ought to be able to compose (hopefully succinctly and elegantly) specific market wager definitions from a structure component and a constraint component. I wonder if this makes sense?
Hi,
Just some general remarks whie reading these posts (I haven't really thought deeply on how I would model your particular problem domain in F#, just commenting on some pointers and ideas given)
0) You seem to be distantiating yourself from OO. I don't think this is necessary or warranted. It's one of the paradigms in your toolbelt, and it has many good uses. F# is not a functional language - it's a functional OO language.
1) Imo, Python (or any dynamic language) is hard to beat as far as fast prototyping goes. F# is certainly better than C# and friends here though. Besides, looks like you have the experimenation phase behind you. I may be biased, but I think F# looks like an ideal language to use in your situation.
2) Robert suggested a 'combinator library' like approach. I agree that libraries written using this approach are the most elegant and flexible I have seen. However, getting there is hard: it takes a deep insight in your problem domain, and a lot of experimentation to get the 'right' decomposition. Much harder than 'divide-and-conquer' functional decomposition. I remember reading about the functional contracts paper that it took them a lot of iterations to get to the decomposition they eventually arrived at (given their background, I found that somewhat disheartening to read...).
3) Since your domain seems to be dealing with money and statistics, you might find the recently added units of measure feature handy (you won't find that in the books you mention - too recent...). Basically, F# can statically check that you're not adding dollars to euros by mistake.
my 2c,
Kurt
Re your points:
0) I'll keep that in mind. I've just come from some dabbling in Scheme and may need to regurgitate some Cool Aid and accept that objects are not all bad :).
1) I'm planning to use F# because I simply cannot abide C# after doing a lot of coding in Python and a fair bit of enjoyable dabbling in PLT Scheme. I have to produce dot Net stuff for work, at the moment, hence the obvious attraction of F#. Whilst I can sometimes get away with Python for even quite large projects, I've gradually come to the dim realisation that proper type discipline can help obviate the creeping worry that 'things are getting out of hand' (which seems to manifest itself in pathological unit testitis in my case) as Python projects grow. Also, although 95% of the time, Python is 'Fast Enough', the other 5% is what people remember when you work in an MS shop where the instinctive reaction to anything open source and different is decidedly lower brain stem in nature. Not expecting a Silver Bullet, but am hopeful that (a) I can learn some useful stuff and (b) gain new insights into my problem domain whilst getting the job done.
2) Agree that teasing out a combinator library is way out of my league for the immediate future as no headhunters from Galois have seen fit to beat a path to my door yet. It will certainly take longer than the completion time for this project for me to reach (if ever) that level of understanding - have to finish tackling the easy squad first.
3) Thanks for the tip - there's a lot to be said for being fastidious about currency handling. I wonder is it possible to define a currency type such that:
(a) the minimum currency amount is (say) 0.50
(b) valid currency amounts are multiples of (say) 0.50
It would be very useful if I could enforce this type of constraint in the type system.
Many thanks for your reply. I hope to ask more specific questions about design approaches as I test more concrete ideas in code.
Topic tags
- f# × 3705
- websharper × 1897
- compiler × 286
- functional × 201
- ui next × 139
- c# × 121
- classes × 97
- web × 97
- .net × 84
- book × 84
- async × 76
- ui.next × 67
- bug × 54
- core × 49
- website × 49
- server × 45
- parallel × 43
- ui × 43
- enhancement × 41
- parsing × 41
- testing × 41
- trywebsharper × 41
- typescript × 37
- html × 35
- javascript × 35
- owin × 35
- asynchronous × 30
- monad × 28
- ocaml × 28
- tutorial × 27
- warp × 27
- haskell × 26
- sitelet × 25
- linq × 22
- workflows × 22
- wpf × 20
- fpish × 19
- introduction × 19
- silverlight × 19
- sitelets × 19
- monodevelop × 17
- rpc × 17
- suave × 17
- piglets × 16
- collections × 15
- feature request × 15
- jquery × 15
- templates × 15
- getting started × 14
- pipeline × 14
- kendoui × 13
- reactive × 12
- 4.1.0.171 × 11
- monads × 11
- opinion × 10
- 4.0.190.100-rc × 9
- deployment × 9
- fixed × 9
- formlets × 9
- in × 9
- json × 9
- plugin × 9
- proposal × 9
- scheme × 9
- solid × 9
- basics × 8
- concurrent × 8
- highcharts × 8
- how-to × 8
- python × 8
- 4.1.1.175 × 7
- complexity × 7
- documentation × 7
- visual studio × 7
- 4.1.2.178 × 6
- lisp × 6
- real-world × 6
- released in 4.0.192.103-rc × 6
- remoting × 6
- resources × 6
- scala × 6
- websharper ui.next × 6
- workshop × 6
- xaml × 6
- 4.0.193.110 × 5
- 4.2.3.236 × 5
- aspnetmvc × 5
- authentication × 5
- azure × 5
- bootstrap × 5
- conference × 5
- dsl × 5
- formlet × 5
- java × 5
- list × 5
- metaprogramming × 5
- ml × 5
- released in Zafir.4.0.188.91-beta10 × 5
- sql × 5
- visualstudio × 5
- websharper.forms × 5
- zafir × 5
- 4.0.192.106 × 4
- 4.0.195.127 × 4
- 4.1.0.38 × 4
- 4.2.1.86 × 4
- 4.2.6.118 × 4
- css × 4
- example × 4
- extensions × 4
- fsi × 4
- fsx × 4
- html5 × 4
- jqueryui × 4
- lift × 4
- reflection × 4
- remote × 4
- rest × 4
- spa × 4
- teaching × 4
- template × 4
- websocket × 4
- wontfix × 4
- 4.0.196.147 × 3
- 4.1.0.34 × 3
- 4.1.6.207 × 3
- 4.2.1.223-beta × 3
- 4.2.11.258 × 3
- 4.2.4.114 × 3
- 4.2.4.247 × 3
- 4.2.5.115 × 3
- 4.2.6.253 × 3
- 4.2.9.256 × 3
- ajax × 3
- alt.net × 3
- aml × 3
- asp.net mvc × 3
- canvas × 3
- cloudsharper × 3
- compilation × 3
- database × 3
- erlang × 3
- events × 3
- extension × 3
- file upload × 3
- forums × 3
- inline × 3
- issue × 3
- kendo × 3
- macro × 3
- mono × 3
- msbuild × 3
- mvc × 3
- pattern × 3
- piglet × 3
- released in Zafir.4.0.187.90-beta10 × 3
- svg × 3
- type provider × 3
- view × 3
- 4.1.1.64 × 2
- 4.1.5.203 × 2
- 4.1.7.232 × 2
- 4.2.10.257 × 2
- 4.2.3.111 × 2
- 4.2.5.249 × 2
- android × 2
- asp.net × 2
- beginner × 2
- blog × 2
- chart × 2
- client × 2
- client server app × 2
- clojure × 2
- computation expressions × 2
- constructor × 2
- corporate × 2
- courses × 2
- cufp × 2
- d3 × 2
- debugging × 2
- direct × 2
- discriminated union × 2
- docs × 2
- elm × 2
- endpoint × 2
- endpoints × 2
- enterprise × 2
- entity framework × 2
- event × 2
- f# interactive × 2
- fable × 2
- flowlet × 2
- formdata × 2
- forms × 2
- fsc × 2
- google maps × 2
- hosting × 2
- http × 2
- https × 2
- iis 8.0 × 2
- install × 2
- interactive × 2
- interface × 2
- iphone × 2
- iteratee × 2
- jobs × 2
- jquery mobile × 2
- keynote × 2
- lens × 2
- lenses × 2
- linux × 2
- listmodel × 2
- mac × 2
- numeric × 2
- oauth × 2
- obfuscation × 2
- offline × 2
- oop × 2
- osx × 2
- packaging × 2
- pattern matching × 2
- performance × 2
- pipelines × 2
- q&a × 2
- quotation × 2
- reference × 2
- released in Zafir.4.0.185.88-beta10 × 2
- rx × 2
- script × 2
- security × 2
- self host × 2
- seq × 2
- sockets × 2
- stm × 2
- tcp × 2
- trie × 2
- tutorials × 2
- type × 2
- url × 2
- var × 2
- websharper.charting × 2
- websharper4 × 2
- websockets × 2
- wig × 2
- xna × 2
- zh × 2
- .net interop × 1
- 2012 × 1
- 4.0.194.126 × 1
- 4.1.3.184 × 1
- 4.1.4.189 × 1
- 4.2.0.214-beta × 1
- 4.2.12.259 × 1
- 4.2.2.231-beta × 1
- 4.2.8.255 × 1
- Canvas Sample Example × 1
- DynamicStyle Animated Style × 1
- Fixed in 4.0.190.100-rc × 1
- Released in Zafir.UI.Next.4.0.169.79-beta10 × 1
- SvgDynamicAttribute × 1
- WebComponent × 1
- abstract class × 1
- accumulator × 1
- active pattern × 1
- actor × 1
- addin × 1
- agents × 1
- aggregation × 1
- agile × 1
- alter session × 1
- animation × 1
- anonymous object × 1
- apache × 1
- api × 1
- appcelerator × 1
- architecture × 1
- array × 1
- arrays × 1
- asp.net 4.5 × 1
- asp.net core × 1
- asp.net integration × 1
- asp.net mvc 4 × 1
- asp.net web api × 1
- aspnet × 1
- ast × 1
- attributes × 1
- authorization × 1
- b-tree × 1
- back button × 1
- badimageformatexception × 1
- bash script × 1
- batching × 1
- binding-vars × 1
- bistro × 1
- body × 1
- bundle × 1
- camtasia studio × 1
- cas protocol × 1
- charts × 1
- clarity × 1
- class × 1
- cli × 1
- clipboard × 1
- clojurescript × 1
- closures × 1
- cloud × 1
- cms × 1
- coding diacritics × 1
- color highlighting × 1
- color zones × 1
- combinator × 1
- combinators × 1
- compile × 1
- compile code on server × 1
- config × 1
- confirm × 1
- content × 1
- context × 1
- context.usersession × 1
- continuation-passing style × 1
- coords × 1
- cordova × 1
- cors × 1
- coursera × 1
- cross-domain × 1
- csla × 1
- current_schema × 1
- custom content × 1
- data × 1
- data grid × 1
- datetime × 1
- debug × 1
- declarative × 1
- delete × 1
- devexpress × 1
- dhtmlx × 1
- dictionary × 1
- directattribute × 1
- disqus × 1
- distance × 1
- do binding × 1
- doc elt ui.next upgrade × 1
- docker × 1
- dojo × 1
- dol × 1
- dom × 1
- domain × 1
- du × 1
- duf-101 × 1
- dynamic × 1
- eastern language × 1
- eclipse × 1
- edsl × 1
- em algorithm × 1
- emacs × 1
- emotion × 1
- enums × 1
- error × 1
- etw × 1
- euclidean × 1
- eventhandlerlist × 1
- examples × 1
- ext js × 1
- extension methods × 1
- extra × 1
- facet pattern × 1
- failed to translate × 1
- fake × 1
- fantomas × 1
- fear × 1
- float × 1
- form × 1
- form-data × 1
- forum × 1
- fp × 1
- frank × 1
- fsdoc × 1
- fsharp × 1
- fsharp.core × 1
- fsharp.powerpack × 1
- fsharpx × 1
- fsunit × 1
- function × 1
- functional style × 1
- game × 1
- games × 1
- gc × 1
- generic × 1
- geometry × 1
- getlastwin32error × 1
- getting-started × 1
- google × 1
- google.maps × 1
- grid × 1
- group × 1
- guide × 1
- hash × 1
- headers × 1
- hello world example × 1
- heroku × 1
- highchart × 1
- history × 1
- how to × 1
- html-templating × 1
- http405 × 1
- httpcontext × 1
- hubfs × 1
- i18n × 1
- ie 8 × 1
- if-doc × 1
- iis × 1
- image × 1
- images × 1
- inheritance × 1
- initialize × 1
- input × 1
- install "visual studio" × 1
- installer × 1
- int64 × 1
- interfaces × 1
- internet explorer × 1
- interop × 1
- interpreter × 1
- io × 1
- iobservable × 1
- ios × 1
- iot × 1
- ipad × 1
- isomorphic × 1
- javascript optimization × 1
- javascript semanticui resources × 1
- jquery-plugin × 1
- jquery-ui × 1
- jquery-ui-datepicker × 1
- js × 1
- kendo datasource × 1
- kendochart × 1
- kendoui compiler × 1
- knockout × 1
- l10n × 1
- learning × 1
- library × 1
- libs × 1
- license × 1
- licensing × 1
- lineserieszonescfg × 1
- local setting × 1
- localization × 1
- logging × 1
- loop × 1
- macros × 1
- mailboxprocessor × 1
- mapping × 1
- maps × 1
- markerclusterer × 1
- markup × 1
- marshal × 1
- math × 1
- mathjax × 1
- message × 1
- message passing × 1
- message-passing × 1
- meta × 1
- metro style × 1
- micro orm × 1
- minimum-requirements × 1
- mix × 1
- mobile installation × 1
- mod_mono × 1
- modal × 1
- module × 1
- mouseevent × 1
- mouseposition × 1
- multidimensional × 1
- multiline × 1
- multithreading × 1
- mysql × 1
- mysqlclient × 1
- nancy × 1
- native × 1
- nested × 1
- nested loops × 1
- node × 1
- nunit × 1
- object relation mapper × 1
- object-oriented × 1
- om × 1
- onboarding × 1
- onclick × 1
- optimization × 1
- option × 1
- orm × 1
- os x × 1
- output-path × 1
- override × 1
- paper × 1
- parameter × 1
- persistence × 1
- persistent data structure × 1
- phonegap × 1
- pola × 1
- post × 1
- powerpack × 1
- prefix tree × 1
- principle of least authority × 1
- privacy × 1
- private × 1
- profile × 1
- programming × 1
- project × 1
- project euler × 1
- projekt_feladat × 1
- protected × 1
- provider × 1
- proxy × 1
- ptvs × 1
- public × 1
- pure f# × 1
- purescript × 1
- qna × 1
- quant × 1
- query sitelet × 1
- question × 1
- quotations × 1
- range × 1
- raphael × 1
- razor × 1
- rc × 1
- reactjs × 1
- real-time × 1
- ref × 1
- region × 1
- released in 4.0.190.100-rc × 1
- reporting × 1
- responsive design × 1
- rest api × 1
- rest sitelet × 1
- restful × 1
- round table × 1
- router × 1
- routing × 1
- rpc reverseproxy × 1
- runtime × 1
- sales × 1
- sample × 1
- sampleapp × 1
- scriptcs × 1
- scripting × 1
- search × 1
- self hosted × 1
- semanticui × 1
- sequence × 1
- serialisation × 1
- service × 1
- session-state × 1
- sharepoint × 1
- signals × 1
- sitelet website × 1
- sitelet.protect × 1
- sitlets × 1
- slickgrid × 1
- source code × 1
- sqlentityconnection × 1
- ssl × 1
- standards × 1
- static content × 1
- stickynotes × 1
- streamreader × 1
- stress × 1
- strong name × 1
- structures × 1
- submitbutton × 1
- subscribe × 1
- svg example html5 websharper.ui.next × 1
- sweetalert × 1
- system.datetime × 1
- system.reflection.targetinvocationexception × 1
- table storage × 1
- targets × 1
- tdd × 1
- templates ui.next × 1
- templating × 1
- text parsing × 1
- three.js × 1
- time travel × 1
- tls × 1
- tooltip × 1
- tracing × 1
- tsunamiide × 1
- turkish × 1
- twitter-bootstrap × 1
- type erasure × 1
- type inference × 1
- type providers × 1
- type-providers × 1
- typeprovider × 1
- ui next forms × 1
- ui-next × 1
- ui.next jqueryui × 1
- ui.next charting × 1
- ui.next formlets × 1
- ui.next forms × 1
- ui.next suave visualstudio × 1
- ui.next templating × 1
- unicode × 1
- unittest client × 1
- upload × 1
- usersession × 1
- validation × 1
- vb × 1
- vb.net × 1
- vector × 1
- view.map × 1
- visal studio × 1
- visual f# × 1
- visual studio 11 × 1
- visual studio 2012 × 1
- visual studio shell × 1
- vs2017 compiler zafir × 1
- vsix × 1
- web api × 1
- web-scraping × 1
- webapi × 1
- webcomponents × 1
- webforms × 1
- webgl × 1
- webrtc × 1
- webshaper × 1
- websharper async × 1
- websharper codemirror × 1
- websharper f# google × 1
- websharper forms × 1
- websharper reactive × 1
- websharper rpc × 1
- websharper sitelets routing × 1
- websharper warp × 1
- websharper-interface-generator × 1
- websharper.chartsjs × 1
- websharper.com × 1
- websharper.exe × 1
- websharper.owin × 1
- websharper.ui.next × 1
- websharper.ui.next jquery × 1
- websockets iis × 1
- why-websharper × 1
- windows 7 × 1
- windows 8 × 1
- windows-phone × 1
- winrt × 1
- www.grabbitmedia.com × 1
- xamarin × 1
- xml × 1
- yeoman × 1
- yield × 1
- zafir beta × 1
- zafir websharper4 × 1
- zarovizsga × 1
![]() |
Copyright (c) 2011-2012 IntelliFactory. All rights reserved. Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us | Terms of Use | Privacy Policy | Cookie Policy |
Built with WebSharper |
I hope that you guys will be able to help me out with a few general approach and design pointers as I work toward porting an application to F#.
I have developed several programs in Python and C# which generate and group exotic multi-race wagers. Examples of such wagers would be what are known as Doubles and Trebles.
Double Wager Example: 11/4 - $0.50
Treble Wager Example: 4/12/1 - $2.00
A wager consists of a *combination* (e.g. 11/4, signifying 11 to win in leg 1 and 4 to win in leg 2) and an amount (e.g. $0.50) to be wagered on that combination. In other words, all doubles consist of an integer pair and an amount, and all trebles consist of an integer 3-tuple and an amount.
Because money is involved, it makes sense to represent amounts as integer cents or use decimal type.
How such wagers are generated is beyond the scope of this question, but suffice it to say that enumerating all possible wager combinations is best done by generating cartesian products of the sets of available runners in each leg. It can actually get more complicated than this. For some particularly exotic exotics, the set of potential combinations might be (say) the cartesian product of the sets of 3-subsets of the available runners in each leg. Having enumerated all possible combinations, one then tests them (somehow) for viability and decides whether or not a wager should be created for each combination.
Sometimes it is necessary to group wager combinations and amounts (a form of compression analogous to the Set Cover Problem) - which can be computationally 'interesting' and requires recourse to various heuristics. Expansion back to constituent single wagers is just cartesian product.
I have been doing my thinking and experimentation in both Python and Scheme here and have learned (after taking up Scheme) that FP/Immutability is a Good Thing (even when it requires threading state up the wazoo) when testing out new heuristics.
I found it fairly easy to develop various wagering programs in Python. It has native tuples and lists (OK, purists would argue that Python lists are not the one true cons cell lists). Python tuples make excellent dictionary keys - something very handy for some of the processing I do on collections of these wager items. Of course it's possible to implement the same functionality in C# (and I have done so), but the amount of boilerplate verbosity required is much greater than in Python and I just find C# and all languages of that ilk painful to think in - at least they are not natural languages for thinking about lists, sets, and tuples! I did successfully implement my Python programs in C#, but I found it very painful and did not enjoy the lack of a REPL.
One reason I am interested in F# is that I wish to transfer as much of the correctness checking to the type system as possible. e.g. it's an error to attempt to make a treble with anything other than 3 runners. When dealing with many different types of exotic, it becomes tedious to code and unit test many constraints which I believe I ought to be able foist on the type system. This is one area where Python falls down. One has to unit test *everything* in order to be able to sleep at night.
So I guess I've finally arrived at the questions I want to ask:
Given that I wish to program as generically as possible such that it is easy for me to later introduce new exotic bet types with just a few new lines of code and without having to go and write many new unit tests:
1) Can I do this succinctly without classes/objects? I am a recovering C++/Java programmer coming to the ML family via Python and Scheme. I now dimly understand that OOP is just one paradigm and that the associated design patterns lore is mostly 'shoehorning' and 'lip sticking the pig'. I have no need of OOP as mental crutch and have enough Scheme under my belt now to be able to conceive of other approaches. But should I or should I not eschew an OOP approach in F# here? Only someone with a deeper understanding can tell me this. I'd really rather not waste too much time forming my own opinion on this as I need to get productive in F# fast.
For example, if I was using PLT Scheme to do this, I would most likely represent exotic wagers with a simple structure and have a module of primitives acting upon these structures and lists of them - the module exporting only those primitives and and composed methods I wished to expose - without recourse to any object system.
Should I take this approach in F# too? I'm not sure what is good style here and particularly wish to avoid being constrained later by bad design choices made now.
2) Does anyone have any particularly brilliant insights about how I can achieve great succinctness, generality, and correctness given the relatively simple data I am operating on? Within my organisation, I'm trying to make a case for much more FP at the computational sharp end. A good deal of what we do seems as if it's ossifying under the weight of class hierarchies (even allowing for the fact that we at least know to favour composition over inheritance most of the time) and everything takes forever to modify, let along experiment with. I really want to take a broom to this. I own shiny new copies of Cousineau, Harrop, Syme et al, so I don't expect to have much trouble in picking up the language per se. But I do want to try to avoid 'writing one to throw away' - right now I really don't have the time for this + am hoping to impress colleagues with 'how easy it is to get it right first time' (hahaha).
My apologies for a rather rambling post and I hope to learn something from your responses!
PS: Don, if you happen across this post, hi from a quondam E-Grouper!