【问题标题】:Modeling the ST monad in Agda在 Agda 中为 ST monad 建模
【发布时间】:2015-12-01 15:16:09
【问题描述】:

最近的SO question 促使我在 Haskell 中编写了一个不安全且纯粹的 ST monad 模拟,您可以在下面看到它的略微修改版本:

{-# LANGUAGE DeriveFunctor, GeneralizedNewtypeDeriving, RankNTypes #-}

import Control.Monad.Trans.State
import GHC.Prim (Any)
import Unsafe.Coerce (unsafeCoerce)
import Data.List

newtype ST s a = ST (State ([Any], Int) a) deriving (Functor, Applicative, Monad)
newtype STRef s a = STRef Int deriving Show

newSTRef :: a -> ST s (STRef s a)
newSTRef a = ST $ do
  (env, i) <- get
  put (unsafeCoerce a : env, i + 1)
  pure (STRef i)

update :: [a] -> (a -> a) -> Int -> [a]
update as f i = case splitAt i as of
  (as, b:bs) -> as ++ f b : bs
  _          -> as

readSTRef :: STRef s a -> ST s a
readSTRef (STRef i) = ST $ do
  (m, i') <- get
  pure (unsafeCoerce (m !! (i' - i - 1)))

modifySTRef :: STRef s a -> (a -> a) -> ST s ()
modifySTRef (STRef i) f = ST $
  modify $ \(env, i') -> (update env (unsafeCoerce f) (i' - i - 1), i')

runST :: (forall s. ST s a) -> a
runST (ST s) = evalState s ([], 0)

如果我们可以在没有unsafeCoerce 的情况下呈现通常的 ST monad API,那就太好了。具体来说,我想正式说明通常的 GHC ST monad 和上述仿真起作用的原因。在我看来,它们之所以起作用,是因为:

  • 任何带有正确s 标签的STRef s a必须在当前ST 计算中创建,因为runST 确保不同的状态不会混淆。
  • 前一点加上 ST 计算只能扩展引用环境这一事实意味着任何带有正确 s 标记的 STRef s a 都指向环境中的有效 a 类型位置(可能在在运行时削弱参考)。

以上几点可实现显着的无需证明义务的编程体验。在我能想到的安全和纯粹的 Haskell 中,没有什么能比得上真正的;我们可以用索引状态单子和异构列表做一个相当糟糕的模仿,但这并没有表达上述任何一点,因此需要在STRef-s 的每个使用站点进行证明。

我不知道我们如何在 Agda 中正确地将其正式化。对于初学者来说,“在 this 计算中分配”已经够棘手了。我曾考虑将STRef-s 表示为特定分配包含在特定ST 计算中的证明,但这似乎会导致类型索引的无休止递归。

【问题讨论】:

  • 您可能想看看 Bernardy 等人的“免费证明”,它考虑了 Agda 中的参数性。显然,添加参数假设不会改变一致性强度。但即使你不想这样做,这篇论文也可能会给你一些想法。
  • 您不只是想要一个可扩展的具有唯一名称的全局状态吗?线性类型,标称逻辑,现有的另一个State...我会坚持索引State monad,就像在提到的SO问题的答案之一中一样。此外,在 Wouter Swiestra 的 thesis 中也有一个非常相似的结构(请注意,现在我们有实例参数,我们可以将证明工作委托给它(我还没有尝试过))。
  • @user3237465 我想有一些“相同状态的旧/新版本”的概念。使用索引状态单子,我们必须每次都证明可以弱化对可能扩展的新状态的引用。我们分配 ref 的状态和我们使用它的状态之间没有必然的关系。我想这是有道理的,因为在没有runST 技巧的情况下,引用可以来自任何地方。

标签: haskell agda st-monad


【解决方案1】:

这是通过假设参数定理完成的某种形式的解决方案。 它还确保假设不会妨碍计算。

http://code.haskell.org/~Saizan/ST/ST.agda

"darcs get http://code.haskell.org/~Saizan/ST/" 获取完整源代码

我对封闭的类型世界不满意,但这是根据我们实际需要调整参数定理的简单方法。

【讨论】:

  • 谢谢。我明白了主要的想法,但这需要一些努力来消化。
  • 链接已失效。有最新版本吗?
  • @WorldSEnder:这是一个可比的 Agda 文件的 persistent link
猜你喜欢
  • 1970-01-01
  • 2019-01-23
  • 2022-01-22
  • 1970-01-01
  • 2017-09-03
  • 2013-07-18
  • 1970-01-01
  • 1970-01-01
  • 2011-10-13
相关资源
最近更新 更多