haskell - 索引单子(monad)的高阶编码如何工作?

标签 haskell monads state-monad

定义索引单子(monad)的常用方法是 Atkey是:

class IxMonad m where
  ireturn :: a -> m i i a
  ibind   :: m i j a -> (a -> m j k b) -> m i k b
McBride 的工作中发现了另一种方法。 (他也讨论过 here ):
type f :-> g = forall i. f i -> g i

class MonadIx (m :: (state -> *) -> (state -> *)) where
  returnIx    :: f :-> m f
  flipBindIx  :: (f :-> m g) -> (m f :-> m g)
flipBindIx的类型与 bindIx :: forall i. m f i -> (forall j. f j -> m g j) -> m g i 同构.而普通的 Haskell monad 是 m :: * -> * 的特征。 (和“正常”索引单子(monad)表征 m :: state -> state -> * -> * ),MonadIx表征单子(monad)m :: (state -> *) -> state -> * .这就是为什么我称后者为“高阶”(但如果有更好的名字,请告诉我)。
虽然这有一定的意义,并且我可以看到两种编码之间的某些结构相似之处,但我在一些事情上遇到了困难。以下是一些似乎相关的问题:
  • 基本上,我只是不明白如何使用 MonadIx编写一个简单的索引状态 monad——IxMonad 中的那个看起来就像常规的状态单子(monad),具有更通用的类型。
  • 相关地,在之前链接的 SO 问题中,Kmett discusses一种“恢复力量”的方法IxMonad来自 MonadIx .然而,该技术并未完全展示(而且我无法再编译相关代码)。
  • MonadIx强于 IxMonad .这表明应该有来自任何 IxMonad m => m i o a 的映射。对一些 MonadIx m => m f (或者是 m f i ?),但不是相反,对吧?那个映射是什么?
  • 最后,MonadIx 的定义中充满了参数性。 .但是IxMonad Action 可以自由地对传入状态的形状提出要求,如 m :: IxMonad m (a, i) i a .这些 Action 在 MonadIx 中的表现如何? ?
  • 最佳答案

    I just don't understand how to use MonadIx to write a simple indexed state monad -- the one that in IxMonad looks just like the regular state monad, with more general types.


    McBride 风格的索引单子(monad)是关于量化运行时不确定性的。如果一个普通的单子(monad) m a对返回 a 的计算进行建模, 一个索引单子(monad) m a i对从 state* i 开始的计算进行建模并返回 a j对于一些 未知输出状态 j .关于 j 你唯一能说的是它满足谓词a .
    *我在这里使用的词“状态”、“输入”和“输出”有点松散。
    这就是为什么 McBride 的 bind具有更高等级的类型:
    mcBind :: m a i -> (forall j. a j -> m b j) -> m b i
    
    继续forall j. a j -> m b j必须不知道 j ,超出了它在运行时通过检查 a j 可以学到的东西. (对于返回多个 a 的非确定性 monad,j 可能对它们中的每一个都不同。)
    McBride 的运行示例来自 the Outrageous Fortune paper是关于可能成功返回打开文件或可能失败(如果文件不存在)的文件 API。 the Hasochism paper 中还有另一个例子关于平铺窗口管理器——你有一个 2D 盒子,它可能由彼此相邻的小盒子组成。您可以深入了解各个框并将其替换为其他框。您不知道每个单独的盒子静态有多大,但是当用另一个盒子替换一个盒子时,它们必须具有相同的大小。
    所以索引状态单子(monad)( State i j a ),它采用已知的输入状态 i并产生一个已知的输出状态j , 就是 不合适用于 McBride 风格的索引单子(monad)。 mcBind的类型是错误的,因为它丢弃了有关输出状态的信息。

    [T]here should be a mapping from any IxMonad [to] MonadIx, but not the reverse, right? What is that mapping?


    这是相反的方式。 McBride 的索引单子(monad)比 Atkey 的更强大——如果你有一个 m :: (i -> *) -> i -> *实例为 MonadIx你总能想出一个对应的n :: i -> i -> * -> *实例为 IxMonad . (Surprisingly the reverse is also true 。)这在 McBride 论文的第 5 节(“天使、恶魔和鲍勃”)中有详细说明。简要地:
    -- McBride wittily pronounces this type "at key"
    data (a := i) j where
        V :: a -> (a := i) i
    
    newtype Atkey m i j a = Atkey { getAtkey :: m (a := j) i }
    
    instance MonadIx m => IxMonad (Atkey m) where
        ireturn a = Atkey (returnIx (V a))
        ibind (Atkey m) f = Atkey $ m `bindIx` (\(V a) -> getAtkey (f a))
    

    关于haskell - 索引单子(monad)的高阶编码如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68613508/

    相关文章:

    haskell - 如何在 Haskell 中表示图表?

    haskell - 如何设置使用 Stack 构建的 Haskell 项目的可执行输出位置?

    haskell ->>= 穷人并发单子(monad)的实现

    haskell - 我想我找到了一个 "non-existent monad"

    haskell - 单子(monad)迭代 Data.Sequence

    haskell - Haskell 数据类型中的默认值

    haskell - 为所有仿函数推广 "sequence"?

    haskell - 反向状态单子(monad)的真实生活和有用的例子

    haskell - 我是否遗漏了 State Monad 的一些基本知识?为什么要分开保存状态和输入?

    haskell - 是否可以在 Haskell 中部分应用第 n 个参数?