【发布时间】:2017-09-07 04:08:43
【问题描述】:
我对 haskell 很陌生,我想我陷入了一些 OO 陷阱。这是我在实现时遇到问题的结构(简化)的草图:
-
作用于样本列表 (Int) 以产生结果 (Int) 的 Observable 的概念
- 一个概念 SimpleObservable 使用某种模式来实现结果(同时会有 Observables 以其他方式实现),例如有点像平均水平
一个函数实例,例如一个平均值乘以常数
我的第一个想法是使用子类;类似的东西(下面有点做作,但希望能传达这个想法)
class Observable a where
estimate :: a -> [Int] -> Int
class (Observable a) => SimpleObservable a where
compute :: a -> Int -> Int
simpleEstimate :: a -> [Int] -> Int
simpleEstimate obs list = sum $ map compute list
data AveConst = AveConst Int
instance Observable AveConst where
estimate = simpleEstimate
instance SimpleObservable AveConst where
compute (AveConst c) x = c * x
但是,即使像上面这样编译它也很丑陋。谷歌搜索告诉我DefaultSignatures 可能会有所帮助,因为我不必为每个实例都做estimate = simpleEstimate,但从围绕它的讨论来看,这样做似乎是一种反模式。
另一种选择是没有子类,但类似(具有相同的Observable 类):
data AveConst = AveConst Int
instance Observable AveConst where
estimate (AveConst c) list = sum $ map (*c) list
但是这样我不确定如何重用该模式;每个Observable 都必须包含完整的estimate 定义,并且会有代码重复。
第三种方式是带有函数字段的类型:
data SimpleObservable = SimpleObservable {
compute :: [Int] -> Int
}
instance Observable SimpleObservable where
estimate obs list =
sum $ map (compute obs) list
aveConst :: Int -> SimpleObservable
aveConst c = SimpleObservable {
compute = (*c)
}
但我也不确定这是否是惯用的。有什么建议吗?
【问题讨论】:
-
"即使上面编译,也很丑。"我有个坏消息:它很丑,并且它不能编译。
-
也许您应该解释您要解决的问题是什么。作为一个非常粗略的直觉,将 Haskell 类型类视为可用于实现 OOP 函数重载的东西。你需要那个来解决你的问题吗?作为一般的经验法则,如果你只有一个实例,这就像有一个重载,所以你实际上不需要类型类。
标签: class haskell default subclassing repeat