2012-12-23 69 views
7

我一直在尋找(並試圖理解)索​​引monad最近。我想我已經把我的頭圍繞着一種索引monad的風格,如下所述:A Neighbourhood of Infinity: Beyond Monads如何實現索引核心風格索引延續monad

但是,我在index-core中發現了一種不同的索引monad風格,其中有些部分似乎對應於帶有兩個索引的索引monad綁定,例如類似的綁定運算符!>=。雖然它明顯對索引有類似的更改,但我不太明白如何使用這些索引,例如,像在其他樣式中一樣控制連續monad中的返回類型。我會對這種索引monad感興趣,主要是因爲它對於monad變換器似乎工作得更好 - 實際上我沒有看到在其他樣式中定義的索引monad變換器(索引monad),只有一個索引變換器正常單子。

我想知道是否有人可以請提供一個實現這種延續monad風格的結果類型連續monad的例子,或者指向我使用這個模塊來定義其他索引monad的其他例子,兩個索引(例如,狀態monad的形式可能會改變狀態的類型)。我一直在尋找這樣一個例子,沒有太多的運氣,而且我還沒有成功地自己實現它。我有一種感覺應該是顯而易見的,但是我在不同的構造函數中受到了一些束縛。

+0

另請參見類似的問題:http://stackoverflow.com/questions/23887237/how-to-implement-index-core-style-indexed-state-monad –

回答

10

我是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實現等同於普通的單子(就像博客文章的版本)的實現:

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庫編寫一個函數是由科納·麥克布賴德的論文的啓發的例子:Kleisli Arrows of Outrageous Fortune。請注意,Conor的方法需要比博客文章更多的冗長性,但它提供了博客文章中沒有的額外功能,主要是能夠在索引中存儲更強大的信息,從而提供更大的靈活性。

這對你來說意味着如果你不需要那些額外的功能,那麼你應該使用你在博客文章中看到的那個。不過,我強烈建議你閱讀Conor的論文,不管你選擇什麼,因爲它是一篇非常出色的論文,並且顯示了Haskell的類型系統有多強大。

我沒有爲index-core實現任何索引monads,主要是因爲我編寫了該庫來爲我寫的另一個庫搔癢。如果你想查看使用index-core具體的代碼,只是檢查出pipes包我曾經index-core實現索引免費單子轉換的2.2.0版本。不過,我不再使用該類型的任何更長的時間,但我還是保持index-core包。

如果您有任何其他疑問,歡迎提問!

+0

非常感謝您的幫助,我想我' VE只是現在弄明白了 - 我已經錯過了位是一個可以使用類似身份的仿函數進行索引功能,無論指數的結果。我設法實現了一個簡單的callCC,轉移和重置。我想知道如何使這個索引monad變壓器?我試圖使用像'NEWTYPE我M I = I(M(I:= I)I)',但我不能讓撫痕工作,因爲索引泄漏到在賓迪函數的返回類型。無論如何,再次感謝您的幫助,我基本上只是因爲學術好奇心而期待。 – DarkOtter

+0

是啊,有沒有很好地解決了指數漏水問題,據我所知。我告訴Conor這件事,但沒有從他那裏聽到。然而,你可以把它變成一個普通的monad變換器,因爲如果你包裝它,普通的monad不會改變索引。 –

+0

你似乎聲稱'(a:= r2)r2 - > Identity r2'與'(a:= r2): - > Identity'相同。你確定這是正確的嗎? –