Hi!
I am trying to understand how to "factor out" common functionality in haskell.
(All the code is available here https://github.com/defigueiredo/inheritance-in-haskell)
I am receiving orderbook data from a Bitcoin Exchange, through their JSON API
(available at https://www.bitstamp.net/api/order_book/)
I have a generic JSON parser that parses the text response and gives me back a generic
JSON object I called Jvalue. This data type represents any JSON object and is defined as follows.
(see json.org for full JSON specs)
------------------
import qualified Data.Map as Map
data Jvalue = Jobject (Map.Map String Jvalue)
| Jarray [Jvalue]
| Jstring String
| Jnumber Double
| Jbool Bool
| Jnull
deriving Show
-------------------
Now, I have to convert this (if possible) into an OrderBook type. An orderbook is basically two lists. One list of the orders placed by people who want to buy, the "bids", and the other with the orders of people who want to sell, the "asks". Each order specifies what price should be paid and how many bitcoins to buy/sell (the volume).
The functions for generating the lists of bids and asks are essentially the same. However, they might need to know if they are creating bids or asks. So, I may need to pass a parameter with that information. I can make that parameter a function or a type (or I may not need it). These three different ideas give rise to 3 different ways to define the orderbook:
1) We can make each Order a type with two constructors (my initial idea):
-------------------
newtype Volume = Volume Double deriving (Show)
newtype Price = Price Double deriving (Show)
data Order = Bid {price::Price, volume::Volume}
| Ask {price::Price, volume::Volume}
deriving (Show)
data OrderBook = OrderBook{ bids::[Order] , asks::[Order] } deriving (Show)
-------------------
2) We can make Bid and Ask types themselves
-------------------
newtype Volume = Volume Double deriving (Show)
newtype Price = Price Double deriving (Show)
data Order = Order {price::Price, volume::Volume} deriving (Show)
newtype Bid = Bid Order deriving Show
newtype Ask = Ask Order deriving Show
data OrderBook = OrderBook{ bids::[Bid] , asks::[Ask] } deriving (Show)
-------------------
3) We can make Order a class
-------------------
newtype Volume = Volume Double deriving (Show)
newtype Price = Price Double deriving (Show)
class Order a where
makeOrder :: String -> String -> a
data Ask = Ask {aprice::Price, avolume::Volume} deriving (Show)
instance Order Ask where
makeOrder = makeAsk
data Bid = Bid {bprice::Price, bvolume::Volume} deriving (Show)
instance Order Bid where
makeOrder = makeBid
data OrderBook = OrderBook{ bids::[Bid] , asks::[Ask] } deriving (Show)
-- makeAsk and MakeBid defined later
-------------------
It is not clear to me which one of these should be used and, most importantly, which criteria should be used to choose between them. I wrote up the code to do the conversion of the Jvalue object into an OrderBook in the 3 different ways. (The third one came out of a discussion from a haskell meetup group.)
(All the code is available here https://github.com/defigueiredo/inheritance-in-haskell)
Any insights on how to choose between them would be *greatly* appreciated!
Thanks,
Dimitri