-- InternalComponent.hs
data ComponentState = ComponentState ...
instance Default ComponentState where ...
componentFunction :: (MonadState InternalComponentState m) => a -> m a
-- Program.hs
data ProgramState = forall cs. ProgramState {
componentState :: cs,
...
}
newtype MyMonad a = MyMonad { runMyMonad :: StateT ProgramState IO a }
myFunction a = do
s <- get
let cs = componentState s
let (r, cs') = runState (componentFunction a) cs
put $ s { componentState = cs' }
return r
我想要的是能够使用 MyMonad
内部的 componentFunction
(在 myFunction
中,如示例中所示),而无需对组件所需的实际状态类型特别感兴趣。将组件状态保留在我自己的状态中并不是必需的,但这就是我在 Haskell 中使用状态的能力。
这实际上可以被视为另一种编程语言中的有状态接口(interface)的实现的等价物:具有某些实现的接口(interface)的实例化提供默认状态值,并且通过该接口(interface)调用的每个函数都可以修改该状态。在任何时候都不会向用户提供实现细节。
如果不清楚,上面的示例失败,因为 myFunction
的实现无法证明记录选择器提供了适当的类型(因为它是存在的);至少我是这么理解的。
最佳答案
您可以通过组件状态的类型来参数化ProgramState
,例如有
data ProgramState cs = ProgramState { componentState :: cs }
这意味着您还必须从 InternalComponent.hs
公开 ComponentState
类型,但不是构造函数。通过这种方式,您可以为类型检查器提供一些可以使用的东西,但不会向 InternalComponent
的用户公开任何内部结构。
关于haskell - 如何为状态类型不透明的有状态组件创建接口(interface)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29333788/