作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试为我在 Haskell 中编写的编译器编写重命名器。
重命名器扫描 AST 以查找符号 DEF,将其输入符号表和符号 USE,通过查找符号表来解决这些问题。
在这种语言中,uses 可以出现在 defs 之前或之后,因此似乎需要 2 pass 策略;一次通过查找所有定义并构建符号表,第二次解决所有用途。
然而,由于 Haskell 是懒惰的(像我一样),我想我可以在实际构建之前将重命名器传递给最终的符号表。只要我 promise 实际构建它就可以了。在命令式编程语言中,这就像及时发送消息一样。这在 Haskell 中确实有效,但必须注意不要引入时间悖论。
这是一个简洁的例子:
module Main where
import Control.Monad.Error
import Control.Monad.RWS
import Data.Maybe ( catMaybes )
import qualified Data.Map as Map
import Data.Map ( Map )
type Symtab = Map String Int
type RenameM = ErrorT String (RWS Symtab String Symtab)
data Cmd = Def String Int
| Use String
renameM :: [Cmd] -> RenameM [(String, Int)]
renameM = liftM catMaybes . mapM rename1M
rename1M :: Cmd -> RenameM (Maybe (String, Int))
rename1M (Def name value) = do
modify $ \symtab -> Map.insert name value symtab
return Nothing
rename1M (Use name) = return . liftM ((,) name) . Map.lookup name =<< ask
--rename1M (Use name) =
-- maybe (return Nothing) (return . Just . (,) name) . Map.lookup name =<< ask
--rename1M (Use name) =
-- maybe (throwError $ "Cannot locate " ++ name) (return . Just . (,) name) . Map.lookup name =<< ask
rename :: [Cmd] -> IO ()
rename cmds = do
let (result, symtab, log) = runRWS (runErrorT $ renameM cmds) symtab Map.empty
print result
main :: IO ()
main = do
rename [ Use "foo"
, Def "bar" 2
, Use "bar"
, Def "foo" 1
]
let (result, symtab, log) = runRWS (runErrorT $ renameM cmds) symtab Map.empty
MonadState
的
RWS
,最终的符号表存储在
MonadReader
.
rename1M
对于
Use
s(2 被注释掉)。在第一种形式中,它工作正常。
rename1M Use
,并取消注释第二个,程序不会终止。然而,在精神上,它与第一种形式没有什么不同。不同的是它有两个
return
s 而不是一个,所以
Maybe
从
Map.lookup
返回必须评估以查看要采取的路径。
MonadWriter
不允许查找更改路径?两通?
最佳答案
当错误发生时,你真的必须中断执行吗?另一种方法是记录错误。打完结后,可以检查错误列表是否为空。我过去采用过这种方法。
-- I've wrapped a writer in a writer transformer. You'll probably want to implement it differently to avoid ambiguity
-- related to writer methods.
type RenameM = WriterT [RenameError] (RWS Symtab String Symtab)
rename1M (Use name) = do
symtab_entry <- asks (Map.lookup name)
-- Write a list of zero or more errors. Evaluation of the list is not forced until all processing is done.
tell $ if isJust symtab_entry then [] else missingSymbol name
return $ Just (name, fromMaybe (error "lookup failed") symtab_entry)
rename cmds = do
let ((result, errors), symtab, log) = runRWS (runWriterT $ renameM cmds) symtab Map.empty
-- After tying the knot, check for errors
if null errors then print result else print errors
关于haskell - Haskell中的祖父悖论,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5525576/
您好,我想以如下图所示的层次结构方式显示数据 这是我的数据库表结构 这是我使用过的查询,但它不是我想要的完美结果 SELECT t1.parent_id AS primary_Id, t2.paren
给定 3 个 Azure DevOps 管道(可能存在更多),如下所示: 构建、单元测试、发布工件 部署暂存、集成测试 部署生产,烟雾测试 如何确保流水线 3 下载流水线 1 中发布的特定工件? 我所
我是一名优秀的程序员,十分优秀!