gpt4 book ai didi

haskell - Haskell 中的 "Strategy Pattern"

转载 作者:行者123 更新时间:2023-12-04 22:12:42 25 4
gpt4 key购买 nike

在 OO 世界中,我有一个类(我们称之为“建议者”),它实现了接近“策略模式”的东西,以在运行时提供算法的不同实现。作为学习 Haskell 的练习,我想重写它。

实际用例非常复杂,所以我将归结为一个更简单的示例。

假设我有一个类Suggester这需要一个规则列表,并将每个规则作为过滤器应用于数据库结果列表。

每个规则都包含三个阶段“构建查询”、“后查询过滤器”和“计分器”。我们基本上最终得到了一个满足以下条件的界面

buildQuery :: Query -> Query
postQueryFilter :: [Record] -> [Record]
scorer :: [Record] -> [(Record, Int)]

Suggestor 需要获取与此接口(interface)匹配的规则列表 - 在运行时动态 - 然后按顺序执行它们。 buildQuery() 必须首先在所有规则中运行,然后是 postQueryFilter,然后是 scorer。 (即我不能将一个规则的函数组合成一个函数)。

在斯卡拉我只是做
// No state, so a singleton `object` instead of a class is ok
object Rule1 extends Rule {
def buildQuery ...
def postQueryFilter ...
def scorer ...
}

object Rule2 extends Rule { .... }

然后可以通过传递相关规则来初始化服务(在运行时根据用户输入定义)。
val suggester = new Suggester( List(Rule1, Rule2, Rule3) );

如果规则是单个函数,这将很简单 - 只需传递函数列表。然而,由于每个规则实际上是三个函数,我需要以某种方式将它们组合在一起,所以我有多个实现满足一个接口(interface)。

我的第一个想法是类型类,但是这些似乎并不能完全满足我的需求——它们需要一个类型变量,并强制我的每个方法都必须使用它——它们没有。
No parameters for class `Rule`

我的第二个想法是将每个模块放在一个 haskell 模块中,但由于模块不是“第一类”,我不能直接传递它们(它们当然不强制接口(interface))。

第三,我尝试创建一个记录类型来封装函数
data Rule = Rule { buildQuery :: Query -> Query, .... etc }

然后为每个定义一个“规则”实例。当在每个模块中完成此操作时,它可以很好地封装并且工作正常,但感觉就像一个 hack,我不确定这是否适合在 haskell 中使用记录?

tl; dr - 我如何将一组函数封装在一起,以便我可以将它们作为匹配接口(interface)的实例传递,但实际上不使用类型变量。

还是我完全是从错误的心态来的?

最佳答案

在我看来,您的解决方案不是“hack”,而是 OO 语言中的“策略模式”:它只需要解决语言的限制,特别是在缺少、不安全或不方便的 Lambdas/Closures/Function 的情况下指针等,因此您需要一种“包装器”,以使其对该语言“可消化”。

一个“策略”基本上是一个功能(可能附有一些额外的数据)。但是如果一个函数真的是语言的第一类成员——就像在 Haskell 中一样,就没有必要将它隐藏在对象壁橱中。

关于haskell - Haskell 中的 "Strategy Pattern",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21677201/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com