在Haskell中正确使用类型类

时间:2016-07-14 17:01:10

标签: haskell

我编写了一个类型类,以避免为不同类型编写重复函数,如下所示:

import Statistics.Distribution.Normal
import Data.Random

d1 :: Double -> Double -> Double -> Double -> Double -> Double
d1 s k r v t = ( log ( s / k ) + ( ( v * v ) / 2 ) * t ) / ( v * sqrt t )

d2 :: Double -> Double -> Double -> Double -> Double -> Double
d2 s k r v t = d1 s k r v t - v * sqrt t

call :: Double -> Double -> Double -> Double -> Double -> Double
call s k r t v = exp ( -r * t ) * ( s * cdf normal ( d1 s k r v t )
                                  - k * cdf normal ( d2 s k r v t ) )
  where normal = Normal (0 :: Double) 1

put :: Double -> Double -> Double -> Double -> Double -> Double
put s k r t v = exp ( -r * t ) * ( k * cdf normal ( - d2 s k r v t )
                                 - s * cdf normal ( - d1 s k r v t ) )
  where normal = Normal (0 :: Double) 1

class Black a where
  price :: a -> Double -> Double -> Double

instance Black ( Option Future ) where
  price ( Option ( Future s ) Call European k t ) r v = call s k r t v
  price ( Option ( Future s ) Put European k t ) r v = put s k r t v

instance Black ( Option Forward ) where
  price ( Option ( Forward s ) Call European k t ) r v = call s k r t v
  price ( Option ( Forward s ) Put European k t ) r v = put s k r t v

这是类型类的有效使用吗?我问的原因是我没有为任何给定类型重载价格函数的定义。我所做的就是避免写作:

priceFuture :: (Option Future) -> Double -> Double -> Double
// impl
priceFoward :: (Option Forward) -> Double -> Double -> Double
impl



data Option a = Option a Type Style Strike Expiration deriving (Show)
data Future = Future Price deriving (Show)
data Forward = Forward Price deriving (Show)

type Barrier = Double
type Expiration = Double
type Price = Double
type Strike = Double
type Value = Double
type Dividend = Double
type Rate = Double

data Type = Call | Put deriving (Eq, Show)
data Style = European | American deriving (Eq, Show)

2 个答案:

答案 0 :(得分:5)

我想我只是让Option的论证成为幻影类型:

data Option a = Option Price Type Style Strike
data Future
data Forward

price :: Option a -> Double -> Double -> Double
price (Option s Call European k t) r v = call s k r t v
price (Option s Put  European k t) r v = put  s k r t v

重复次数少得多,并且不需要类型类,但如果您需要其他选项,您仍然会在前向选项(Option Forward)和将来的选项(Option Future)之间获得类型级别的区别。如果您真的很兴奋,可以打开DataKinds以确保FutureForwardOption唯一两个可能的类型级参数。

答案 1 :(得分:1)

这个怎么样?

data Option = Option ForFut Type Style Strike Expiration deriving (Show)
data ForFut = Forward Price | Future Price deriving (Show)

type Barrier = Double
type Expiration = Double
type Price = Double
type Strike = Double
type Value = Double
type Dividend = Double

type Rate = Double

data Type = Call | Put deriving (Eq, Show)
data Style = European | American deriving (Eq, Show)

call :: Double -> Double -> Double -> Double -> Double -> Double
call = undefined

put :: Double -> Double -> Double -> Double -> Double -> Double
put = undefined

price :: Option -> Double -> Double -> Double
price ( Option ( Future s ) Call European k t ) r v = call s k r t v
price ( Option ( Future s ) Put European k t ) r v = put s k r t v
price ( Option ( Forward s ) Call European k t ) r v = call s k r t v
price ( Option ( Forward s ) Put European k t ) r v = put s k r t v

因此,我将ForwardFuture类型合并为一种类型。这样就无需使Option成为更高级的类型。然后可以删除类型类,并且可以使用简单的模式匹配来定义price