propellor/doc/todo/info_propigation_out_of_nes...

98 lines
3.1 KiB
Plaintext
Raw Permalink Normal View History

> Now [[fixed|done]]!! --[[Joey]]
2015-01-24 17:04:06 +00:00
Currently, Info about a Host's Properties is propigated to the host by
examining the tree of Properties.
2014-07-07 03:39:32 +00:00
2015-01-24 17:04:06 +00:00
This works, but there's one problem. Consider this example:
2014-07-07 03:39:32 +00:00
withOS desc $ \o -> case o of
(Just (System (Debian Unstable) _)) -> ensureProperty foo
_ -> ensureProperty bar
2015-01-24 17:04:06 +00:00
Here, the Info of `foo` is not propigated out. Nor is `bar`'s Info.
It's not really clear if just one Info, or both should be propigated out.
2014-12-08 00:31:22 +00:00
2014-12-07 23:20:02 +00:00
----
2014-07-07 03:39:32 +00:00
One approach might be to make the Propellor monad be able to be run in two
2014-12-07 22:49:42 +00:00
modes. In run mode, it actually performs IO, etc. In introspection mode, all
liftIO is a no-op, but all Info encountered is accumulated using a Reader.
This might need two separate monad definitions.
That is surely doable, but consider this example:
property "demo" = do
needfoo <- liftIO checkFoo
if needfoo
then ensureProperty foo
2015-01-24 17:04:06 +00:00
else ensureProperty . bar =<< liftIO (getBarParam)
2014-12-07 22:49:42 +00:00
In introspection mode, the liftIO is a no-op, but needs to return a Bool.
That seems unlikely (how to pick which?), but even if some defaulting is
used, only one of foo or bar's info will be seen.
2015-01-24 17:04:06 +00:00
Worse, the bar property is not fully known until IO can be performed to get
its parameter.
2014-12-07 23:20:02 +00:00
----
2014-12-07 22:49:42 +00:00
Another approach could be something like this:
withInfoFrom foo $ \callfoo ->
withInfoFrom bar $ \callbar ->
property "demo" = do
needfoo <- liftIO checkFoo
if needfoo
then callfoo
else callbar
2015-01-24 17:04:06 +00:00
Here withInfoFrom adds foo and bar as child properties of the demo property
that (may) call them.
2014-12-07 22:49:42 +00:00
This approach is not fully type safe; it would be possible to call
withInfoFrom in a way that didn't let it propigate the info.
2015-01-24 17:04:06 +00:00
And again this doesn't solve the problem that IO can be needed to get
a parameter of a child property.
2014-12-07 22:49:42 +00:00
----
2014-12-07 23:20:02 +00:00
Another approach would be to add a new SimpleProperty, which is a property
that has no Info. Only allow calling ensureProperty on this new type.
(Or, remove propertyInfo from Property, and add a new InfoProperty that
has the info.)
2014-12-08 00:31:22 +00:00
But, propertyList can only contain one type at a time,
2014-12-07 23:20:02 +00:00
not a mixed list of Property and SimpleProperty.
Could a GADT be used instead?
{-# LANGUAGE GADTs #-}
{-# LANGUAGE EmptyDataDecls #-}
data HasInfo
data NoInfo
2014-12-08 00:31:22 +00:00
data Property = IProperty (GProperty HasInfo) | SProperty (GProperty NoInfo)
data GProperty i where
GIProperty :: Desc -> Propellor Result -> Info -> GProperty HasInfo
GSProperty :: Desc -> Propellor Result -> GProperty NoInfo
ensureProperty :: GProperty NoInfo -> Propellor Result
ensureProperty (GSProperty d r) = r
That works. I made a `gadtwip` git branch that elaborated on that,
to the point that Property.File compiles, but is otherwise
unfinished. Most definitions of `Property` need to be changed to
`GProperty NoInfo`, so that ensureProperty can call them. It's a big,
intrusive change, and it may complicate propellor too much.
2014-12-07 23:20:02 +00:00
2015-01-24 17:04:06 +00:00
I've tried to make this change a couple times now, and not been completely
successful so far.
2014-12-08 00:31:22 +00:00
(I may need to make instances of Prop for `GProperty NoInfo` and `GProperty
HasInfo`, if that's possible, and make more Property combinators work on
Prop.)