私は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
。はr
インデックスになります。
IFunctor
およびの実装IMonad
は、通常のモナドの実装と同じです(ブログ投稿のバージョンと同じです)。
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
唯一の違いは、余分なノイズR
とIdentity
ノイズです。ブログ投稿のバージョンと一致させることを選択した場合は、これらを抽象化できます。
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のアプローチでは、ブログ投稿のアプローチよりも詳細度が必要ですが、主に、より強力な情報をインデックスに格納してさらに柔軟性を高める機能など、ブログ投稿のアプローチにはない追加機能が提供されます。
つまり、これらの追加機能が必要ない場合は、ブログ投稿で見たものを使用する必要があります。ただし、コナーの論文は非常に優れた論文であり、ハスケルの型システムがいかに強力であるかを示しているため、何を選択しても読むことを強くお勧めします。
のインデックス付きモナドは実装しませんでしたindex-core
。主な理由は、自分が作成した別のライブラリのかゆみを掻くためにそのライブラリを作成したためです。を使用する具体的なコードを確認したい場合は、インデックス付きの無料モナド変換子を実装するために使用したパッケージのindex-core
バージョン2.2.0
を確認してください。しかし、私はまだパッケージを維持していますが、そのタイプはもう使用していません。pipes
index-core
index-core
他にご不明な点がございましたら、お気軽にお問い合わせください。