【问题标题】:State Monads in HaskellHaskell 中的状态单子
【发布时间】:2012-04-19 21:28:51
【问题描述】:

我正在用 Haskell 编写一个函数,该函数接收一个 Java 类文件,并编写另一个相同但包含一些修改的类文件。为此,我觉得我绝对需要一个状态单子来至少保存包含类文件所有字节的 [Word8]。然而,在我对 Haskell 中的 State Monads 进行了所有研究之后,我仍然无法弄清楚如何做到这一点。谁能指出我正确的方向?我希望能够有一个 [Word8](或者你知道,任何数据类型),它在所有函数的范围内,并且我可以从函数中修改。我知道这涉及使用类似的东西 状态

但我真的不知道从哪里开始定义 monad 之类的。

提前非常感谢!

【问题讨论】:

  • 您将对字节进行什么样的转换?你在插入和删除块吗?你需要随机访问吗?在你担心你需要哪个 monad 之前,首先要弄清楚你需要什么样的数据结构。这要重要得多。
  • 另外,我猜this question 的答案对你有用。

标签: haskell functional-programming monads


【解决方案1】:

我不确定你是否想要State monad。根据您要进行的修改类型,您被允许只将要修改的数据传递给要修改它的每个函数。 State 通常用于您生成值除了来修改状态的情况,即当您编写许多看起来像s -> (s,a) 的函数时。

首先尝试一种正常功能的方法。 State 并不神奇,它只是让某些类型的代码更容易快速、简洁和正确地编写。你可以用它做的一切你也可以不用它,只是有点乏味。

【讨论】:

  • 谢谢,我最终只使用了很多模拟状态变化的普通函数。万一有人好奇,该项目涉及读取类文件,将其分成几部分,并在方法中添加代码以在输入方法时打印出方法的名称。再次感谢!
【解决方案2】:

您可能想要的是 ST monad 和可变向量,而不是 State Monad。

使用 IO monad 从类文件中读取字节。

bytes <- readFile myClassFile

使用runST 对给定字节运行ST monad 计算:

let result = runST $ transform bytes

ST monad 让您可以访问mutable vectors,这很像 C 或 Java 数组。它们由整数索引,并且具有 O(1) 的查找和修改时间。

transform :: [Char] -> ST s [Char]
transform bytes = do
   mvec <- thaw $ fromList bytes
   -- you can read a value at an index
   val <- read mvec 0
   -- and set a value at an index
   write mvec 0 (val `xor` 0xff)
   -- ...
   -- turn it back into a list of bytes
   vec <- freeze mvec
   return $ toList vec

因此,只需将 mvec 传递给您的所有函数(必须返回 ST 操作),您就可以对字节执行任何操作。

如果您不想费心将其作为参数传递,请考虑使用 ReaderT monad 转换以使 mvec 隐式可用于您的所有代码。

transform bytes = do
   -- ...
   runReaderT other mvec
   --- ... 

other :: ReaderT (MVector s Char) (ST s) String 
other = do
   -- ...
   -- grab the mvec when you need it
   mvec <- ask
   val <- lift $ read mvec 77
   lift $ write mvec 77 (val * 363 - 28)
   -- ...
   return "Hi!"

当然,这一切都假设您需要随机访问字节。如果您不...那么您可能不需要MVector

例如,如果您只需将 0xDEADBEEF 的每个实例替换为 0xCAFEBABE,您可以只使用列表,不需要 ST monad:

 let newBytes = intsToBytes . map (\i -> if i == 0xDEADBEEF then 0xCAFEBABE else i) $ bytesToInts bytes

【讨论】:

  • 可变向量让你 O(1) 读写,但插入和删除是 O(n),所以我不确定这是最好的选择,除非你确定你没有改变类文件中的字节数。
  • @DanBurton:你知道,我什至没有想到 Pha3drus 可能会这样做。好电话!
猜你喜欢
  • 2018-07-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-16
相关资源
最近更新 更多