![]() |
1
39
您的代码段有很多问题。我修复了你的代码片段,添加了关于什么被破坏的解释,并添加了一些风格建议(如果你愿意的话)。
-用简单定义替换导入类型-
{- 不是你问题的一部分,而是我的2分… 如果您不想更改您所在州的收藏 使用一个类型别名,你必须在使用它的任何地方进行搜索。相反,只是 必要时更改这些定义 -}
{- statet int中的int是什么?名称更容易阅读,原因 并且要改变。声明性ftw让我们改用行号 -}
{- 让我们使用“real”类型,这样就可以派生实例。 由于pass1不是单次传输,即未定义为pass1 m a, 在最深的状态下使用statet没有意义,即statet[地址]标识 那么我们就用一个州[地址] -}
{- 让我们从最外面剥下那堆(声明中的lefmost) 最深处是你最初的声明中的身份。 请注意,runwritert不处于启动状态… runstatet(和runstate)的第一个参数不是初始状态 但是单子…让我们翻转吧! -}
{- 既然最后一个函数不执行您想要的操作,因为您希望提供 要用writert附加到的初始日志。 因为它是一个单体变压器,我们会在这里做一些技巧。 -}
{- 您打算直接从pass1堆栈调用popline吗? 如果是这样,您需要“教”pass1成为“单子状态行” 为此,让我们派生pass1(这就是我们用newtype声明它的原因!) -}
{- 最好保持通用,但我们现在可以写: popline::pass1(可能是line) -}
{- 好的,现在我得到int=>行号…. 我们可以创建pass1和monadState行号的实例,但是linenumber 不应该弄乱,所以我会直接对斜坡进行编码。 如果需要,可以提供一个Monadander实例供咨询。
-}
这里有一个冗长的响应,但是Monad和Monad堆栈,正如您首先看到的,是具有挑战性的。我修改了代码,但我鼓励您播放和检查各种函数的类型,以了解正在发生的事情,并与原始函数进行比较。Haskell的类型推断意味着通常类型注释是多余的(除非消除歧义)。一般来说,我们给函数赋的类型不太通用,因为它是推断的,所以最好不要键入annotate。类型注释确实是一种很好的调试技术;) 干杯 P.S.Real World Haskell关于Monad变压器的章节非常出色: http://book.realworldhaskell.org/read/monad-transformers.html |
![]() |
2
12
一般来说,您会发现,对于您需要的所有状态位,使用一个具有更大复合结构的statet,代码最终会更清晰。一个很好的原因是,当你想到一个状态时,你忘记了你总是可以一个字段地增长结构,你可以使用记录糖写出单个字段的更新,或者使用类似fclabels或数据访问器包的东西来操作状态。
|
![]() |
trpnd · 如何定义由两个任意单声道变压器组成的单声道变压器? 3 年前 |
![]() |
Fabus1184 · Haskell mapM_不打印 3 年前 |
![]() |
Gotthold · 基于范数约束向量的类型 3 年前 |
![]() |
jian · haskell将另一个函数用作输入参数 3 年前 |
![]() |
Jocafrei · 用Haskell函数实现最大公约数函数 6 年前 |