复杂状态 Monad 结构
我仍然是 Haskell 的新手,我想我现在已经无法理解了。我的代码如下所示。
data World = World {
intStack :: [Int],
boolStack :: [Bool]
} deriving Show
instance IntStack World where
getIntStack = intStack
putIntStack ints (World _ bools) = World ints bools
instance BoolStack World where
getBoolStack = boolStack
putBoolStack bools (World ints _) = World ints bools
class IntStack a where
getIntStack :: a -> [Int]
putIntStack :: [Int] -> a -> a
class BoolStack a where
getBoolStack :: a -> [Bool]
putBoolStack :: [Bool] -> a -> a
(<=>) :: (IntStack c, BoolStack c) => c -> c
(<=>) w = putIntStack xs . putBoolStack ((x == x'):bs) $ w
where (x:x':xs) = getIntStack w
bs = getBoolStack w
(<+>) :: (IntStack c) => c -> c
(<+>) w = putIntStack ((x+x'):xs) w
where (x:x':xs) = getIntStack w
我的重点(现在忽略函数中的错误情况)是能够将 (<=>) 和 (<+>) 等函数链接在一起,假设底层数据类型实现了函数所需的接口。
我觉得我可以用状态 monad 来清理它,但我不确定如何构造它以允许更改实现 IntStack、BoolStack 等的任何数据类型。
我知道这是一个非常模糊的描述,但我觉得上面的代码可能是绝对错误的方法。
感谢您的任何反馈!
I am still a newbie to Haskell and I think I am over my head right now. I have code that looks like the following.
data World = World {
intStack :: [Int],
boolStack :: [Bool]
} deriving Show
instance IntStack World where
getIntStack = intStack
putIntStack ints (World _ bools) = World ints bools
instance BoolStack World where
getBoolStack = boolStack
putBoolStack bools (World ints _) = World ints bools
class IntStack a where
getIntStack :: a -> [Int]
putIntStack :: [Int] -> a -> a
class BoolStack a where
getBoolStack :: a -> [Bool]
putBoolStack :: [Bool] -> a -> a
(<=>) :: (IntStack c, BoolStack c) => c -> c
(<=>) w = putIntStack xs . putBoolStack ((x == x'):bs) $ w
where (x:x':xs) = getIntStack w
bs = getBoolStack w
(<+>) :: (IntStack c) => c -> c
(<+>) w = putIntStack ((x+x'):xs) w
where (x:x':xs) = getIntStack w
My focus (For now ignoring error cases in the functions) is being able to chain together functions like (<=>) and (<+>) assuming that the underlying data type implements the function's required interfaces.
I feel like I can clean this up a lot with a state monad, but I am not sure how to structure it to allow changes to whatever data type that implements IntStack, BoolStack, etc..
I know that this is a horribly vague description, but I feel like the code I have above is probably the absolutely wrong way to go about it.
Thanks for any feedback!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
恭喜,您刚刚发明了镜头!抽象
[Int]
和[Bool]
类型,并使用data
而不是class
,你会得到一些东西就像...它是在 Hackage 上的六个包中实现的。大多数至少提供:
getIntStack
/putIntStack
和getBoolStack
/putBoolStack
导出投影镜头的能力数据声明World
,然后从intStack
中挑选intStack
。 code>World) 和垂直组合(并行运行两个镜头,每个镜头在一对的一侧)State
和StateT
的一些接口(例如Lens ab -> State br 类型的东西) -> 声明 a r
),这将允许您在[Bool]
或[Int]
上编写计算,并像在 a 上进行计算一样运行它们世界
所以,看看黑客攻击!有
data-lens
系列,其中包括核心、推导能力,以及有状态接口; lens 包;和 pointless-lenses 包。可能还有一些我也忘记了。Congratulations, you've just invented lenses! Abstract the
[Int]
and[Bool]
types, and usedata
instead ofclass
, and you get something like...which is implemented in half a dozen packages on Hackage. Most offer at least:
getIntStack
/putIntStack
andgetBoolStack
/putBoolStack
directly from a data declarationWorld
out of some larger structure, then picking theintStack
out of theWorld
) and vertical composition (running two lenses in parallel, each on one side of a pair)State
andStateT
(e.g. something of typeLens a b -> State b r -> State a r
), which would let you write computations on a[Bool]
or[Int]
and run them as if they were computations on aWorld
So, check out hackage! There's the
data-lens
family, which includes a core, the deriving ability, and the stateful interface; the lens package; and the pointless-lenses package. There are probably some I forgot, too.您可以在状态单子中实现推送和弹出操作,并使用它们来实现您的功能:
You could implement push and pop operations in the state monad, and use them to implement your functions: