我想用不同的值标记树的每个元素(Int,例如清酒).我设法做到这一点,但代码是丑陋的野兽,我不知道如何使用Monads.
我的看法:
data Tree a = Tree (a, [Tree a])
tag (Tree (x, l)) n = ((m, x), l')
where (m,l') = foldl g (n,[]) l
where g (n,r) x = let ff = tag x n in ((fst $ fst ff) +1, (Tree ff):r)
Run Code Online (Sandbox Code Playgroud)
你知道更好的方法吗?
编辑: 我刚才意识到上面的foldl确实是mapAccumL.所以,这是上面的清洁版本:
import Data.List (mapAccumL)
data Tree a = Tree (a, [Tree a])
tag (Tree (x, l)) n = ((m,x),l')
where (m,l') = mapAccumL g n l
g n x = let ff@((f,_),_) = …Run Code Online (Sandbox Code Playgroud) 我想使用节点和唯一键的IntMap创建图形结构.这里和这里已经很好地介绍了这个主题.我理解状态monad是如何工作的,基本上将状态函数 - >(val,state)包装在newtype中,这样我们就可以为它创建一个monad实例.我已经阅读了很多相关主题.我仍然无法理解如何在程序执行过程中获得唯一(或仅增量)值.获得一系列连续的ID很容易,但是一旦我"runState"退出monad,似乎我回到了我开始跟踪当前ID的位置.我觉得我被卡在了monad中.我考虑的另一个选择是保持整个IntMap和当前"下一个"ID作为状态,但这似乎非常"必要"和极端.这个问题非常相似,但没有得到很多答案(或者我可能只是错过了一些明显的答案).在程序执行过程中利用状态monad获取唯一ID的惯用方法是什么?谢谢.
我正在为Haskell中的简单命令式语言编写编译器,输出Java字节码.我已经到了我发出字节码的抽象表示的地步.
在编写用于编译if语句的代码时遇到了一些麻烦.要实现if语句,我需要跳转到标签.因此,我需要为该标签生成一个名称,该名称必须是唯一的.
我的第一个想法是通过一些状态compileStatement,即
compileStatement :: Statement -> UniqueIDState -> [AbstractInstruction]
Run Code Online (Sandbox Code Playgroud)
当然,compilerStatement是递归的,所以使用这种方法需要我从递归调用中将唯一ID生成器的状态传递回upp:
compileStatement :: Statement -> UniqueIDState -> (UniqueIdState, [AbstractInstruction])
Run Code Online (Sandbox Code Playgroud)
这看起来有点笨拙,特别是如果我意识到我需要在将来携带更多状态; 有更优雅的方式吗?