Last active
February 27, 2025 04:22
-
-
Save debasishg/e1b846e8a34aefe5784271f0ddf861e3 to your computer and use it in GitHub Desktop.
Revisions
-
debasishg revised this gist
Nov 16, 2023 . No changes.There are no files selected for viewing
-
debasishg revised this gist
Nov 16, 2023 . 1 changed file with 3 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -56,4 +56,6 @@ module Trade(TaxFeeForMarket: TaxFee) : Trade_sig = struct end ``` This defines a functor that takes a `TaxFee` module and returns a `Trade` module. Note that it takes the signature of the `TaxFee` module which only publishes the basic interface and no implementation. The complete implementation is [here](https://github.com/debasishg/tradeioml). -
debasishg revised this gist
Nov 16, 2023 . 1 changed file with 2 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,3 +1,5 @@ # Abstraction and Parametricity implementing domain models in OCaml One of my favorite comments on abstraction and parametricity .. > Parametricity can be thought of as the dual to abstraction. Where abstraction hides details about an implementation from the outside world, parametricity hides details about the outside world from an implementation. -
debasishg revised this gist
Nov 15, 2023 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -54,4 +54,4 @@ module Trade(TaxFeeForMarket: TaxFee) : Trade_sig = struct end ``` This defines a functor that takes a `TaxFee` module and returns a `Trade` module. Note that it takes the signature of the `TaxFee` module which only publishes the basic interface and no implementation. -
debasishg created this gist
Nov 15, 2023 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,57 @@ One of my favorite comments on abstraction and parametricity .. > Parametricity can be thought of as the dual to abstraction. Where abstraction hides details about an implementation from the outside world, parametricity hides details about the outside world from an implementation. When using OCaml as the implementation language, you abstract using **ADTs (Abstract Data Types)** and make your abstraction parametric using **functors**. And bind all of the algebras together using **Modules**. ## Abstraction In a domain model for trading systems, I have an ADT for the Trade model, specified by * A module that has a type, called its signature. With `Trade_sig` as the signature of the trade module, only the names mentioned in the signature are exported outside the module. ```ocaml module type Trade_sig = sig (* names to be exported *) end ``` * An implementation of the module type that remains completely hidden from the world outside the module. ```ocaml module Trade : Trade_sig = struct (* implementations *) end ``` The above modules form the **abstraction** part in the quote above. ## Parametricity One part in the trade model deals with the handling of tax and fees which varies with the market/country where the trade is made, while our trade model above needs to be generic across all markets. So the trade model has to *abstract over* the structure that implements the signature of the `TaxFee` module. Yes, we need to think in terms of modules for the tax/fee structure since they are the primary units of modularity that OCaml offers as first class values. This is **parametricity** and in OCaml you do this with functors. Functors are nothing but functions from modules to modules. In our case we will have a functor that maps the TaxFee module to the Trade module. First we define a module signature for `TaxFee`. ```ocaml module type TaxFee = sig type t (* tax/fee rates for every tax/fee applicable for the market *) val tax_fee_rates : (t * float) list (* list of tax/fees applicable for the market *) val tax_fees : market -> t list end ``` And then use this to define the functor for `Trade` ```ocaml module Trade(TaxFeeForMarket: TaxFee) : Trade_sig = struct (* implementations *) end ``` This defines a functor that takes a `TaxFee` module and returns a `Trade` module. NNote that it takes the signature of the `TaxFee` module which only publishes the basic interface and no implementation.