类结构的设计模式

问题描述 投票:1回答:1

我的目标是以优雅和高效的方式表示一组具有相似行为的类型。为实现此目的,我创建了一个使用单一类型的解决方案,然后使用了一组执行模式匹配的函数。

我的第一个问题是:有一种方法可以使用单个类型类来表示相同的想法,而不是每个变体都具有一个构造函数来实现该类型类的类型?

以下两种方法中的哪一种是:-Haskell中更好的公认设计模式?-记忆效率更高?-表现更好?-更优雅,为什么?-易于使用的代码使用者?

方法1:单一类型和模式匹配

假设具有以下结构:

data Aggregate a
  = Average    <some necessary state keeping>
  | Variance   <some necessary state keeping>
  | Quantile a <some necessary state keeping>

它的构造函数不是公共的,因为这会暴露内部状态。相反,存在一组构造函数:

newAverage :: Floating a
  => Aggregate a
newAverage = Average ...

newVariance :: Floating a
  => Aggregate a
newVariance = Variance ...

newQuantile :: Floating a
  => a                     -- ! important, a parameter to the function
  -> Aggregate a
newQuantile p = Quantile p ...

一旦创建了对象,我们就可以执行两个功能:将put值放入其中,一旦满意,我们就可以将get当前值:

get :: Floating a
  => Aggregate a
  -> Maybe a
get (Average <state>) = getAverage <state>
get (Variance <state>) = getVariance <state>
get (Quantile _ <state>) = getQuantile <state>

put :: Floating a
  => a
  -> Aggregate a
  -> Aggregate a
put newVal (Average <state>) = putAverage newVal <state>
put newVal (Variance <state>) = putVariance newVal <state>
put newVal (Quantile p <state>) = putQuantile newVal p <state>

方法2:类型类和实例

class Aggregate a where
  new :: a
  get :: Floating f => a f -> Maybe f
  put :: Floating f => 

data Average a = Average Word64 a
data Variance a ...

instance Aggregate Average where

instance Aggregate Variance where

instance Aggregate Quantile where

这里明显的问题是new不是参数化的,因此无法使用Quantile参数初始化p。向new添加参数是可能的,但是这将导致所有其他非参数构造函数忽略该值,这不是一个好的设计。

haskell design-patterns pattern-matching typeclass
1个回答
0
投票

很难给出一般性建议。我倾向于使用方法1。请注意,您可以使用

data Aggregate a
  = Average    AverageState
  | Variance   VarianceState
  | Quantile a QuantileState

并导出上面的每个构造函数,仅将...State类型保留为模块专用。

[在某些情况下可能可行,但在其他情况下则不可行,因此必须根据具体情况进行评估。

关于方法2,如果周围有很多构造函数/类型,这可能会更方便。要解决new问题,可以使用[

中的类型家族(或眼底)
class Floating f => Aggregate a f where
  type AggregateNew a f
  new :: AggregateNew a f -> a f
  get :: a f -> Maybe f
  put :: ...

instance Floating f => Aggregate Average f where
  type AggregateNew (Average a) f = ()
  new () = ...

instance Aggregate Quantile where
  type AggregateNew (Quantile a) f = a
  new x = ...
© www.soinside.com 2019 - 2024. All rights reserved.