7

我最近一直在看(并试图理解)索​​引单子。我想我已经了解了一种索引 monad 的风格,如下所述:A Neighborhood of Infinity: Beyond Monads

但是,我在index-core中发现了一种不同风格的索引 monad ,它的某些部分似乎与这个带有两个索引的索引 monad 绑定相对应,例如类似的绑定运算符!>=。虽然它显然对索引有类似的更改,但我不太明白如何使用这些索引,例如,像使用其他样式一样控制延续 monad 中的返回类型。我会对这种索引 monad 风格感兴趣,主要是因为它似乎对 monad 转换器工作得更好——事实上,我还没有看到以另一种风格定义的索引 monad 转换器(索引 monad),只有一个索引转换器常规单子。

我想知道是否有人可以提供一个实现为这种延续 monad 风格的两种结果类型延续 monad 的示例,或者指出使用此模块定义其他使用两个索引的索引 monad 的其他示例(例如例如,状态类型可能改变的状态单子的形式)。我一直在寻找这样的例子,没有太多运气,我自己也没有成功实现它。我觉得这应该很明显,但是我在不同的构造函数中有点束缚。

4

1 回答 1

9

我是index-core包的作者,答案是可以的。这是解决方案:

{-# LANGUAGE TypeOperators, RankNTypes #-}

import Control.Category.Index
import Control.IMonad
import Data.Functor.Identity

newtype ICont f a i = ICont { runICont :: (a :-> f) -> f i }

请注意,我使用f而不是r. s将r成为索引。

IFunctor和的实现IMonad与普通 monad 的实现相同(就像博客文章的版本一样):

instance IFunctor (ICont f) where
    fmapI f m = bindI (returnI . f) m

instance IMonad (ICont f) where
    returnI a = ICont $ \k -> k a
    bindI f m = ICont $ \k -> runICont m $ \a -> runICont (f a) k

诀窍是意识到它会减少到您在博客文章中看到的版本f = Identity

  (a -> r2) -> r1
~ (a -> Identity r2) -> Identity r1
~ ((a := r2) r2 -> Identity r2) -> Identity r1
~ ((a := r2) :-> Identity) -> Identity r1
~ ICont Identity (a := r2) r1
~ R ICont Identity r1 r2 a

唯一的区别是额外RIdentity噪音,如果您选择匹配博客文章的版本,您可以将其抽象掉:

type ICont' r1 r2 a = ICont Identity (a := r2) r1

这是使用编写的函数的示例ICont

-- example ~ (String -> Int) -> Char
-- example ~ ((String := Int) Int -> Identity Int) -> Identity Char
example :: ICont' Char Int String
example = ICont $ \k -> Identity $
    case runIdentity (k (V "Hello")) of
        0 -> 'A'
        _ -> 'B'

index-core图书馆的灵感来自 Conor McBride 的论文:Kleisli Arrows of Outrageous Fortune。请注意,Conor 的方法比博客文章中的方法需要更多的详细信息,但它提供了博客文章中没有的额外功能,主要是能够在索引中存储更强大的信息,从而提供更大的灵活性。

这对您来说意味着,如果您不需要那些额外的功能,那么您可能应该使用您在博客文章中看到的那个。但是,无论您选择什么,我都强烈建议您阅读 Conor 的论文,因为它是一篇非常出色的论文,并展示了 Haskell 类型系统的强大功能。

我没有index-core为 . 如果您想查看使用的具体代码index-core,只需查看我用来实现带索引的免费 monad 转换器2.2.0的包的版本。但是,我不再使用该类型,尽管我仍然维护包。pipesindex-coreindex-core

如果您还有其他问题,请随时提问!

于 2012-12-24T14:52:28.800 回答