Of course, each plug-in will have a different type for the status of the plug-in, so I focus on how I can integrate it into my system in a general way.
Perhaps you can use the existential type to hide the state of the plugin, something like
{-
Now each plugin has the same type, and yet different values of the plugin can have internal states of different types:
charPlugin :: Plugin charPlugin = Plugin 'a' (\ps es e -> (succ ps,es)) intPlugin :: Plugin intPlugin = Plugin (1::Int) (\ps es e -> (succ ps,es))
(I took inspiration from the Fold
type from the foldl package, which uses existences in a similar way.)
Now you can have a list of plugins:
plugins :: [Plugin] plugins = [charPlugin,intPlugin]
A possible evolution of the project would be to limit the internal states to instances of some type:
data Plugin = forall ps. Show ps => Plugin { currentState :: ps , transition :: ps -> EditorState -> Event -> (ps, EditorState) }
I suspect that a Monoid
instance might be defined for the Plugin
type.
In addition, we could explicitly specify Plugin
parameterization on the type of events that it receives, for example
data Plugin e = ...
In this case, the plugin could be made an instance of Contravariant
and possibly Divisible
.
And if we break up and parameterize the state of the editor
data Plugin es e = ...
then perhaps we could find a way to “enlarge” this plugin to work in a more general state than the one for which it was defined.