2016-11-19 8 views
2

:プラグインのライターは次のようになり、単一の機能を提供します。自分のタイプのユーザープラグインはどのように処理できますか?私はHaskellのモジュール式で拡張可能なテキストエディタを書いていると私は、このような方法で、プラグインを実装したいと思い

handleEvent :: (PluginState, EditorState) -> Event -> (PluginState, EditorState) 

として、各イベントが発生すると、プラグインは、現在のエディタ状態および独自の状態のカスタマイズされたチャンクを使用して、新しいエディタ状態および新しいプラグイン状態を計算することができる。もちろん、それぞれのPluginはPlugin状態のために別のTypeを持っているので、私はこれを自分のシステムに一般的な方法でどのように組み込むことができますか。

は、どのように私は漠然と、このような何かを書くことができます。

type Plugin = (PluginState, EditorState) -> Event -> (PluginState, EditorState) 
data MyEditor = MyEditor EditorState [Plugin] [PluginState] 

PluginStateが、具体的なタイプではないのですか?

TLDR;すべてのプラグインの状態タイプをグローバルな状態にベーキングせずに、非具体的な型の値のマップをアクセス可能な方法で保存するにはどうすればよいですか?私は新しいプラグインが追加されたときにエディタを再コンパイルしても問題ありません。

ありがとうございます!私は本当にこの1つに固執しています:/

あなたが何か明確化が必要な場合はお問い合わせください!

+0

これの出発点は、GHCがプラグインをどのように処理し、Yiがどのように設定を処理するかを調べることです。どちらも部分再コンパイルのアプローチを取っています... – Alec

+1

https://hackage.haskell.org/package/vaultのケースのように聞こえます – Gurkenglas

答えて

1

もちろん、各プラグインはプラグインの状態が異なるため、私はこれを自分のシステムに一般的な方法でどのように組み込むことができますか。

{-# LANGUAGE ExistentialQuantification #-} 

data Plugin = forall ps. Plugin { 
     currentState :: ps 
    , transition :: ps -> EditorState -> Event -> (ps, EditorState) 
    } 

handleEvent :: Plugin -> EditorState -> Event -> (Plugin,EditorState) 
handleEvent (Plugin ps t) es e = 
    let (ps',es') = t ps es e 
    in (Plugin ps' t,es') 

よう

は、おそらくあなたは、プラグインの状態を非表示にするexistential typeを使用することができ、何かが今、それぞれのプラグインは、同じタイプのものであり、まだ別のプラグインの値は、異なる種類の内部状態を持つことができます。

charPlugin :: Plugin 
charPlugin = Plugin 'a' (\ps es e -> (succ ps,es)) 

intPlugin :: Plugin 
intPlugin = Plugin (1::Int) (\ps es e -> (succ ps,es)) 

(私は類似したにexistentialsを使用していますfoldlのパッケージからFoldタイプからインスピレーションを取りました

plugins :: [Plugin] 
plugins = [charPlugin,intPlugin] 

デザインの可能性進化は、いくつかの型クラスのインスタンスであることを内部状態を拘束するために、次のようになります:

data Plugin = forall ps. Show ps => Plugin { 
     currentState :: ps 
    , transition :: ps -> EditorState -> Event -> (ps, EditorState) 
    } 

。あなたは今、プラグインのリストを持つことができる方法)

タイプのMonoidインスタンスが定義されている可能性があります。

また、私たちは、プラグインは、同様Contravariant、おそらくDivisibleのインスタンスを作ることができるその場合

data Plugin e = ... 

のように、明示的なイベントの種類、それが受け入れにPluginをパラメータと考えることができます。

そして、我々は野生行くと、エディタの状態に

data Plugin es e = ... 

をパラメータならば、おそらく我々は、「ズーム」、それがあったために1以上の一般的な状態で動作するように指定したプラグインをする方法を見つけることができ定義された。

+0

適用時に作業するのは少し面倒です(私はトランジション関数を解凍しなければなりません。その後、状態を再パックし、移行関数を新しいプラグインに戻して戻します)、それ以外は魅力的です!ありがとう! –

+0

@Chris Pennerパッキングのアンパックは 'handleEvent'のような単一の関数で扱うことができます。また、 'Plugin'型は、スペースリークを避けるために厳密なフィールドを持つべきです。 – danidiaz

関連する問題