Haskell - 我如何 运行 状态单子列表?
Haskell - How would I run a list of state monads?
我对 Haskell 有点陌生,我在使用 State monad 时遇到了一些麻烦。
我创建了以下类型。
Stat a
有一个 monoid、functor、applicative 和 monad 实例为其创建。
我程序中的 "main" 类型是生物,它有很多参数:
data Creature = Creature {
strength :: Stat Integer,
dexterity :: Stat Integer,
...
}
data Stat a = Stat {
modifiers :: [StatModifier],
stat :: a
}
data StatModifier = StatModifier {
modifierType :: ModifierType,
value :: Integer
}
data ModifierType =
Enhancement
| Morale
| ...
一个生物会发生很多事情。我选择用状态 monad 来表示那些东西:
anyPossibleChange :: State Creature Creature
这可能是对生物造成的伤害,增加生物的力量,基本上任何东西。任何事情的可能性让我认为 State monad 在这里是一个不错的选择。我将接受原始状态的生物,进行一些修改,然后 return 元组中的原始状态和新状态。
原始状态可能是:
Creature {
strength = Stat [] 10,
dexterity = Stat [] 10
}
结束状态可能是:
Creature {
strength = Stat [StatModifier Enhancement 2] 10,
dexterity = Stat [StatModifier Enhancement 4, StatModifier Morale 2] 10
}
我想建立一个生物需要经历的所有变化的列表,然后 运行 生物经历所有这些变化。
这是我想要的签名,但我在想出一个实现时遇到了麻烦。我愿意接受它的不同。
applyChanges :: Creature -> [State Creature Creature] -> Creature
我觉得我应该可以用弃牌来做到这一点,可能 FoldM
但我的大脑被这些类型所困扰。
什么是好的实施?
State Creature Creature
是这种计算的错误类型。如您所见,您可以摆脱它,但它不必要地使事情复杂化,因为您实际上根本不关心状态变量!您只需使用它来存储函数的原始输入...然后将其丢弃在 applyChanges
.
一种更容易使用的类型是 Creature -> Creature
,然后如果您有要应用的此类函数的列表,您只需将它们全部组合起来,您可以使用折叠来完成:
applyChanges :: [Creature -> Creature] -> Creature -> Creature
applyChanges = foldr (.) id
我对 Haskell 有点陌生,我在使用 State monad 时遇到了一些麻烦。
我创建了以下类型。
Stat a
有一个 monoid、functor、applicative 和 monad 实例为其创建。
我程序中的 "main" 类型是生物,它有很多参数:
data Creature = Creature {
strength :: Stat Integer,
dexterity :: Stat Integer,
...
}
data Stat a = Stat {
modifiers :: [StatModifier],
stat :: a
}
data StatModifier = StatModifier {
modifierType :: ModifierType,
value :: Integer
}
data ModifierType =
Enhancement
| Morale
| ...
一个生物会发生很多事情。我选择用状态 monad 来表示那些东西:
anyPossibleChange :: State Creature Creature
这可能是对生物造成的伤害,增加生物的力量,基本上任何东西。任何事情的可能性让我认为 State monad 在这里是一个不错的选择。我将接受原始状态的生物,进行一些修改,然后 return 元组中的原始状态和新状态。
原始状态可能是:
Creature {
strength = Stat [] 10,
dexterity = Stat [] 10
}
结束状态可能是:
Creature {
strength = Stat [StatModifier Enhancement 2] 10,
dexterity = Stat [StatModifier Enhancement 4, StatModifier Morale 2] 10
}
我想建立一个生物需要经历的所有变化的列表,然后 运行 生物经历所有这些变化。
这是我想要的签名,但我在想出一个实现时遇到了麻烦。我愿意接受它的不同。
applyChanges :: Creature -> [State Creature Creature] -> Creature
我觉得我应该可以用弃牌来做到这一点,可能 FoldM
但我的大脑被这些类型所困扰。
什么是好的实施?
State Creature Creature
是这种计算的错误类型。如您所见,您可以摆脱它,但它不必要地使事情复杂化,因为您实际上根本不关心状态变量!您只需使用它来存储函数的原始输入...然后将其丢弃在 applyChanges
.
一种更容易使用的类型是 Creature -> Creature
,然后如果您有要应用的此类函数的列表,您只需将它们全部组合起来,您可以使用折叠来完成:
applyChanges :: [Creature -> Creature] -> Creature -> Creature
applyChanges = foldr (.) id