【发布时间】:2026-01-14 20:00:01
【问题描述】:
考虑一下,你有 Nel 状态(Nel 代表 NonEmptyList,使事情更短), 并且您想将状态组合为一个状态,使用一些函数 f,用于状态的左侧部分和 g 表示状态的正确部分。
所以你想要这样的东西:
def foldStatesG[S, A](in: NonEmptyList[State[S, A]])(f: (A, A) => A)(g: (S, S) => S): State[S, A] = {
in.foldLeft1((s1, s2) => State(e => {
val ss1 = s1(e)
val ss2 = s2(e)
g(ss1._1, ss2._1) -> f(ss1._2, ss2._2)
}))
}
我敢肯定,我正在发明自行车,而且这种东西已经存在,可能以更一般的方式存在。但是,通过 scalaz 我没有找到或认出它。如果您对此主题有任何帮助,将不胜感激。
第二个问题,描述了我是如何遇到这样的问题的。我想做一个小模拟,当你有一个敌人(考虑它只是一个双),以及所有可能击中他的法术Nel[Spell]。所以基本上我想生成所有可能的序列。例如,如果 Nel[Spell] = ($, #),那么给定一个敌人 E,进程看起来像
E -> (), then Nel(E -> $, E -> #), then Nel(E -> $$, E -> ##, E -> $#, E-> #$) etc.. (pseudo code)
无需过多介绍,我需要这样的东西:
def combineS(variations: NonEmptyList[Spell]): State[NonEmptyList[(Enemy, List[Spell])], Boolean]
换句话说,你为它提供了所有可能的动作,它模拟了所有可能的状态。您可以将其视为一种决策树,每一步都有分支。 因此,我定义了如何继续使用一个咒语。
def combineS1(spell: Spell): State[(NonEmptyList[(Enemy, List[Spell])]), Boolean]
// some logic
问题是,我无法通过简单的遍历来实现它:
def combineS(variations: NonEmptyList[Spell]): State[NonEmptyList[(Enemy, List[Spell])], Boolean] = {
val x = variations traverse combine1 // State[Nel[..], Nel[Boolean]
x map { _.suml1(conjunction)}
}
因为在遍历中,Nels 不是相互附加的,而是被丢弃的。 这就是我想出这个解决方案的原因:
def combineS(variations: NonEmptyList[Spell]): State[NonEmptyList[(Enemy, List[Spell])], AllDead] = {
val x: NonEmptyList[State[NonEmptyList[(Enemy, List[Spell])], Boolean]] = variations map combineS
foldStates(x)(_ && _)(append)
}
该代码实际上是有效的,但我觉得有一种方法可以遍历它,而无需额外的 foldState。
进行此类模拟的其他功能方法是什么(至少在概念方面)。我可以简单地编写它,而不使用高级概念,但这个练习的目的正是为了学习高级的东西。 (也许这正是作家 Monad 的工作?还是 Comonad?)
另外,如果 * 不是解决此类问题的最佳场所,请指出,此类问题应该在哪里提出?
【问题讨论】:
-
我认为这是 Stack Overflow 的一个好问题——只是还没有机会回答。
标签: scala functional-programming state scalaz