【发布时间】:2017-02-07 06:24:11
【问题描述】:
我是 Haskell 的新手,我正在寻找为证券交易所库建模。它是一个库,因此由用户定义细节。我打算使用它的方式是让用户定义这样的东西。
data MyExchange = MyExchange { name :: ExchangeName
, base :: Currency
, quote :: Currency }
deriving (Eq, Show)
instance Exchange MyExchange
data MyExchangeBookMessage =
MyExchangeBookMessage { time :: Time
, exchange :: MyExchange
, price :: Price
, side :: Side
, amount :: Maybe Amount }
deriving (Eq, Show)
instance ExchangeBookMessage MyExchangeBookMessage
我尝试了以下方法,但立即遇到了类型类的一些限制。下面是代码和错误信息。具体来说,用多种类型参数化类型类的替代方法是什么?
这是库的代码
module Lib where
data Side = Buy | Sell deriving (Eq, Show)
newtype Amount = Amount Rational deriving (Eq, Show)
newtype Price = Price Rational deriving (Eq, Show)
newtype Currency = Currency String deriving (Eq, Show)
newtype Time = Time Integer deriving (Eq, Show)
type ExchangeName = String
class Exchange a where
name :: a -> ExchangeName
base :: a -> Currency
quote :: a -> Currency
class Message a where
time :: a -> Time
class (Message a, Exchange e) => ExchangeMessage a e where
exchange :: a -> e
class ExchangeMessage a b => BookMessage a b where
price :: a -> Price
side :: a -> Side
amount :: a -> Maybe Amount
还有错误信息:
src/Lib.hs:22:1: error:
• Too many parameters for class ‘ExchangeMessage’
(Use MultiParamTypeClasses to allow multi-parameter classes)
• In the class declaration for ‘ExchangeMessage’
以后我希望能够实现这样的类型类:
class Strategy s where
run (Message m, Action a) => s -> m -> a
在Strategy 实现中,run 函数将采用抽象消息 m,将其与相关的 Message 数据构造函数进行模式匹配并返回特定操作。
我正在移植一些 Scala 代码。在 Scala 中,我在底部使用了带有具体案例类的特征层次结构:
trait Exchange {
def name: String
def base: Currency
def quote: Currency
}
case class MyExchange(base: Currency, quote: Currency) {
val name = "my-exchange"
}
trait Message {
def time: Long
}
trait ExchangeMessage extends Message {
def exchange: Exchange
}
trait BookMessage extends ExchangeMessage {
def price: Double
def side: Side
def amount: Option[Double]
}
case class MyBookMessage(time: Long, price: Double, side: Side, amount: Option[Double]) {
def exchange: Exchange = MyExchange(...)
}
【问题讨论】:
-
有一个建议给
Use MultiParamTypeClasses to allow multi-parameter classes,建议你采纳。将{-# LANGAUGE MultiParamTypeClasses #-}放在文件的第一行以启用它。 -
这会“工作”,但是当您尝试使用
BookMessage的任何方法时会遇到其他问题。我不确定b应该在那里...... -
@luqui:
BookMessageextendsExchangeMessage:b是来自ExchangeMessage的Exchange的类型。 -
@luqui:我不确定这是否是对该域建模的最佳方式。如果没有更好的处理方法,我会求助于
MultiParamTypeClasses。 -
我想到了另外一点:Haskell 不是一种面向对象的语言,因此过渡可能会很艰难。由于您的大脑不习惯于函数式建模,您可能会尝试的一种技术是直接编写库的一些客户端代码,然后重构直到找到它应该使用的库。
标签: haskell types algebra domain-model