索引 monad 的高阶编码是如何工作的?

How does the higher-order encoding of indexed monads work?

定义索引 monad a la 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 (also discussed by him ):

的工作中找到的
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 monads 表征 m :: * -> *('normal' 索引 monads 表征 m :: state -> state -> * -> *),MonadIx 表征 monads m :: (state -> *) -> state -> *。这就是为什么我称后者为 'higher-order'(但如果有更好的名字,请告诉我)。

虽然这有一定的道理,而且我可以看到两种编码之间的某些结构相似性,但我在一些事情上遇到了困难。以下是一些看似相关的问题:

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 m a 模拟一个 return 是一个 a 的计算,一个索引的 monad m a i 模拟一个从 state* i 和 [=对于某些 未知输出状态 j,62=] 是一个 a j。关于 j 你唯一能说的就是它满足谓词 a.

*我在这里使用的词“状态”、“输入”和“输出”有些松散。

这就是 McBride 的 bind 具有更高等级类型的原因:

mcBind :: m a i -> (forall j. a j -> m b j) -> m b i

continuation forall j. a j -> m b j 必须与 j 无关,超出它在运行时通过检查 a j 可以学习的内容。 (对于 return 多个 a 的非确定性单子,每个 j 可能不同。)

McBride 的 运行 来自 the Outrageous Fortune paper is about a file API which may successfully return an open file or may fail (if the file doesn't exist). There's another example in the Hasochism paper 的示例关于平铺 window 管理器 — 您有一个 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))