如何实现索引核心样式的索引延续monad

时间:2012-12-23 21:03:35

标签: haskell monads

我最近一直在寻找(并试图理解)索​​引monad。我想我已经掌握了一种索引monad样式,如下所述:A Neighbourhood of Infinity: Beyond Monads

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

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

1 个答案:

答案 0 :(得分: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代替rr将成为指数。

IFunctorIMonad的实现与普通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实现任何索引monad,主要是因为我编写了该库来为我写的另一个库划伤我的痒。如果您想查看使用index-core的具体代码,只需查看我使用2.2.0的{​​{1}}包的版本pipes来实现索引的免费monad转换器。但是,我不再使用该类型,但我仍然保留index-core包。

如果您有任何其他问题,请随时提出!