如何从主要的kickadart monad变压器堆栈?

时间:2016-08-12 09:27:41

标签: haskell monads monad-transformers state-monad

这是我前一个问题的后续问题:State and IO Monads

我的目标是为文件创建一个简单的文本编辑器。我已经有了一个Editor组件,可以很好地封装基础数据结构上的所有编辑操作。

感谢上一个问题的答案,我能够重构我的程序,以便我现在有一个很好的monad变换器堆栈:

type Session = StateT AppState (StateT Editor IO)

AppState保存应用程序的全局状态(当前打开文件等),而Editor表示应用程序编辑组件的内部状态(插入符号所在的位置)等等......)我有一个函数是应用程序的主要驱动程序:

eventLoop :: Session ()

到目前为止一直很好,但是现在我不知道如何从main函数启动变换器堆栈? Main必须返回IO monad中的某个东西,它位于我的堆栈的最底层。我的猜测是我必须初始化AppState,然后执行以下操作:

main = do
  let initialAppState = ...
  return $ runStateT eventLoop initialAppState

但是我现在在哪里初始化Editor

令我困惑的是,在重构之前,Editor只是AppState的成员:

data AppState = { editor :: Editor , ... }

但现在它已经移出AppState并成为变压器堆栈的某个兄弟。 Editor不应该AppState仍然是Session的一部分,因为修改它意味着修改整体状态吗?

如何使用AppStateEditor正确初始化main,然后从我的<table class="table table-condensed table-bordered table-hover"> <tr> <th>Report</th> <th>Type</th> <th>Date</th> </tr> @foreach($tableContent as $data) <tr> <td><input type="checkbox" name="report" value="reportValue" id="{{$data->id}}" >{{$data->title}} </input></td> <td><b>{{$data->report_type}}</b></td> <td>{{$data->created_at}}</td> </tr> @endforeach </table> <a class="btn btn-default" href="/deletereport/"{{--how do I get checked box id here ? --}}">Delete</a> 运行它?

1 个答案:

答案 0 :(得分:2)

  

我如何从主函数中启动变压器堆栈?

main =
  flip evalStateT initialAppState $
  flip evalStateT initialEditorState $
  eventLoop
  where
    initialAppState =
      error "Define me"
    initialEditorState =
      error "Define me"
  

编辑器是否仍然是AppState的一部分,因为修改它意味着修改整体状态?

取决于。

请记住,Monad Transformer的目的是以临时方式扩展功能吗? ad-hoc我的意思是,不重写现有的代码库,而是添加它。因此,如果您已经拥有了编辑器和AppState的隔离API,那么将它们组合到另一个&#34; dome&#34;中会更容易。模块使用变压器堆栈。

OTOH,从最初的架构角度来看,AppState是一个包含编辑器(我将其命名为EditorState)的数据结构等等,这是完全有道理的。在这样的cas中,AppState的API应该封装Editor的API。 &#34;镜头&#34;库将帮助您使用这种复合数据结构(尽管我必须提到它有一个陡峭的学习曲线)。