On Tue, Jul 26, 2011 at 11:58 PM, Tim Cowlishaw <t...@timcowlishaw.co.uk>wrote:

> On Tue, Jul 26, 2011 at 11:14 PM, Alexander Solla <alex.so...@gmail.com>
> wrote:
>
> > data OrderType = Market Size | Limit LimitPrice Expiration Size | Stop
> > (Either Percent Price)
> > newtype Sell = Sell OrderType
> > newtype Buy = Buy OrderType
> > newtype Order = Order (Either Buy Sell)
>
> > size :: Order -> Int
> > size (Order (Left (Buy (Market s))) = s
> > size (Order (Left (Buy (Limit _ _ s))) = s
> > etc.
>
> Aah, thank you - this is really neat. So now, I can write (for
> instance) an Eq instance for OrderType and use deriving (Eq) on the
> newtypes that wrap it, and my Order can be a concrete type, but still
> encapsulates all the different types of order.
>
> Thank you!
>

No problem.  This is more-or-less how type classes work internally, with
fewer restrictions (but some more implicit passing around of stuff).  Notice
that my Order type "corresponds" with your Order typeclass.  My OrderType
type value constructors correspond to all your Order types.  In other words,
a typeclass is a fancy "open" "union" type.  I never use type classes unless
I need that openness property.

The problem with this approach is that it can become verbose very quickly.
 It can be mitigated some by defining accessors for the newtypes, and using
function composition.

So instead of:
> newtype Sell = Sell OrderType
> newtype Buy = Buy OrderType
> newtype Order = Order (Either Buy Sell)

I would personally use
> newtype Sell = Sell { unSell :: OrderType }
> newtype Buy = Buy { unBuy :: OrderType }
> newtype Order = Order { unOrder :: Either Buy Sell }

where "un" should be read like "unwrap".  These unwrappers can help cut down
on the size of pattern matches.  I'll give an example shortly.

I suggested using Maybe to deal with nonsense semantics/undefinedness.  All
orders have a size/quantity, but not all have a limit price.  So we might
write an accessor like:

limitPrice' :: OrdeType -> Maybe Price
limitPrice'  (Limit l _ _) = Just l
limitPrice' _ = Nothing

We have turned a "partial" function into a "total" function by embedding it
in (Order -> Maybe Price).  This cuts down on bugs.

Now that easy accessor for all orders:

limitPrice :: Order -> Maybe Price
limitPrice = limitPrice' . either (unBuy) (unSell) . unOrder

We might even want to stick limitPrice' in a where clause for limitPrice,
depending on whether you expect reuse or not.
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to