2017-01-12 4 views
1

私の毎週のレンズの質問の時間;ズームモナドスタックのコンテキスト

私はモナドスタックを持っている:

newtype Action a = Action 
    { runAct :: StateT ActionState (ReaderT Hooks IO) a 
    } deriving (Functor, Applicative, Monad, MonadState ActionState, MonadReader Hooks, MonadIO) 

data ActionState = ActionState 
    { _ed :: Editor 
    , _asyncs :: [AsyncAction] 
    } 

私は私のエディタレンズが依存HasEditor型クラスを生成するEditorタイプにmakeClassyを使用。

Editorには、多くの場合、Bufferがあります。私は、特定のバッファ(BufAction)上で動作するアクションのための別のモナドスタックタイプを定義しました。唯一の違いは、StateTがBufferの上にあるということである:私は特定のバッファにStateTをズームするzoom (editor.buffers.ix selected)を使用BufActionを実行するために

newtype BufAction a = BufAction 
    { runBufAct::StateT Buffer (ReaderT Hooks IO) a 
    } deriving (Functor, Applicative, Monad, MonadState Buffer, MonadReader Hooks, MonadIO) 

。問題は、現在BufActionの中にeditor以上のレンズを使用したり、HasEditorを必要とするレンズを使用できなくなったことです。

Actionはすべて、BufActionの内部で実行され、BufActionActionの内部で実行できません。この場合、BufActionには完全なActionStateが必要ですが、実行するには特定のバッファへの参照も必要です。 ActionにはActionStateが必要です。したがって、BufActionはより限定的なモナドであり、Actionを埋め込み可能にする必要があります。

だから、約私はこのようなタイプのいくつかの並べ替えたい:GHCはこれにチョークしかし

newtype Action a = forall s. HasEditor s => Action 
    { runAct :: StateT s (ReaderT Hooks IO) a 
    } deriving (Functor, Applicative, Monad, MonadState s, MonadReader Hooks, MonadIO) 

を。 newtypeに存在と制約を処理することはできません。

dataタイプに切り替えました。しかし、私はGeneralizedNewtypeDerivingを失い、手動で 節を派生させるすべてを実装する必要があります。私は本当にやっていないだろう。

また、タイプエイリアスを試しました。これは私がtypeclassesを派生する必要はありませんが、私はエラーを他のデータ型にも埋め込んでいるため、エラーが発生します。私はここにActionを使用するので、たとえば:異なるタクトを取る

• Illegal polymorphic type: Action() 
    GHC doesn't yet support impredicative polymorphism 
• In the definition of data constructor ‘ActionState’ 
    In the data type declaration for ‘ActionState’ 

;:

data ActionState = ActionState 
{ _ed :: Editor 
, _asyncs :: [Async (Action())] 
, _hooks :: Hooks 
, _nextHook :: Int 
} 

私はに実行します私も柔軟MonadStateインスタンスを実行しようとしました:

instance (HasEditor s, HasBuffer s) => (MonadState s) BufAction where 

が、取得:

• Illegal instance declaration for ‘MonadState s BufAction’ 
    The coverage condition fails in class ‘MonadState’ 
     for functional dependency: ‘m -> s’ 
    Reason: lhs type ‘BufAction’ does not determine rhs type ‘s’ 
    Un-determined variable: s 
• In the instance declaration for ‘(MonadState s) BufAction’ 

をMonadStateが機能の依存関係を使用しているので...

本当にこの1に貼り付け、私は使用することができますハンド!

ありがとうございました!私は本当に助けに感謝します!

+0

質問の種類が不明です。 「BufAction」の状態が「Action」よりも小さい場合、どのように動作するのでしょうか?の状態?確かにそれは他の方法ラウンドする必要がありますか? –

+0

申し訳ありませんが、それは不明です。私は少し詳しく説明しようとします。 BufActionは 'Action'よりも小さい状態を使用しますが、 'より多くの情報'を持つ状態であるため、それほど「小さな状態」ではありません。 'BufAction'が'(ActionState、BufId) 'として利用できる状態を考えることができます。本質的に 'ActionState'全体が(' Action'と同じように)利用可能ですが、特定のバッファにも焦点を合わせることができる情報があります。したがって、 'ActionState'で動作する' Action'は 'BufAction'でも利用できるはずです。 'BufAction'は' BufId'コンテキストを必要とし、 'Action'では実行できません。任意の明確な? –

+0

これはもちろん、BufActionが実際に大きな状態を含むものに変更する必要があります。それはHasEditorとHasBufferという制約が参照するものです。 'Action'は' HasEditor'だけの状態で実行されます。 'BufAction'は' HasEditor'と 'HasBuffer'で状態を超えて実行する必要がありますので、より制限的です。 –

答えて

0

これはあなたが私にやろうとしているようです。どの種類の状態が受け入れられるかについての制約は、アクション自体ではなく、アクションを使用する定義に指定されます。次に、レンズパッケージのzoom機能を使用して、たとえばEditorBufferに焦点を当てることができます。

{-# Language TemplateHaskell #-} 
{-# Language GeneralizedNewtypeDeriving #-} 
{-# Language MultiParamTypeClasses #-} 
{-# Language FlexibleInstances #-} 
{-# Language TypeFamilies #-} 
{-# Language UndecidableInstances #-} -- for the Zoomed type instance 

module Demo where 

import Control.Monad.State 
import Control.Monad.Reader 
import Control.Lens 

data Hooks 

data SomeState = SomeState 
    { _thing1, _thing2 :: Int } 

makeLenses ''SomeState 

newtype Action s a = Action 
    { runAct :: StateT s (ReaderT Hooks IO) a 
    } deriving (Functor, Applicative, Monad, MonadState s) 

instance Zoom (Action a) (Action s) a s where 
    zoom l (Action m) = Action (zoom l m) 

type instance Zoomed (Action s) = Zoomed (StateT s (ReaderT Hooks IO)) 

example :: Action Int a -> Action SomeState a 
example = zoom thing1 
+0

面白い、興味深い;それはうまくいくかもしれません! –

関連する問題