See --[[Joey]] Needs ghc newer than 7.6.3. It may be possible to port Data.Type.Equality and Data.Type.Bool to older versions; I got them to compile but they didn't work right. --[[Joey]] I have a `resourceconflict` branch that adds this in Propellor.Resources, but it is not yet integrated into the Property types. --[[Joey]] [[!tag user/joey]] > On the `typed-os-requirements` branch, I have the UsingPort 80 singleton > implemented. As soon as I tried to apply it to some apache properties > though, I realized a problem -- If multiple apache vhosts are defined > each as its own property, then each of those properties can't have > UsingPort 80. Because the idea is to not allow combining 2 properties > that use the same pprt. > > Similarly, Apache.installed can't have UsingPort 80, because each of the > vhost properties requires that, and would inherit it. > > So, this could be used for non-vhost stuff, like simple web servers, tor > nodes, etc. But how to handle vhosts? > > Of course, there could be a single property that defines all of a host's > apache vhosts, and it could then have UsingPort 80. But that loses the > flexible composition of properties. > > I suppose we could include the server: `UsingPort 80 Apache` > (or `UsingPort 80 "apache"` to avoid needing a data type with all the > servers. Or even write it `"apache" '> 80`) > And allow combining properties that have the same server on the same > port. Don't allow combining `UsingPort 80 Apache` with `UsingPort 80 Ngnix` > > --[[Joey]] > > Also, it's not clear how to parameterize properties that support > > running a service on different ports. One way might be to > > declare the ports in the type signatures; the property code > > can then use `usedPorts (getMetaTypes self)` to get a port list. > > > > So, we'd start with a property definition that does not use any ports: > > > > virtualHost :: Domain -> WebRoot -> RevertableProperty DebianLike DebianLike > > virtualHost domain docroot = > > let self = property "vhost" (go (usedPorts (getMetaTypes self))) > > in self > > where > > go [] = error "No ports specified" > > go ports = ... > > > > And then to use it: > > > > & virtualHost "example.com" "/var/www" :: RevertableProperty (UsingPort 80 + DebianLike) DebianLike > > > > But, this seems like a mouthful to write! > > > > Maybe make a `using` that changes the metatypes of a property, > > adding a resource. That shortens what needs to be written some: > > > > & virtualHost "example.com" "/var/www" `using` (port :: UsingPort 80) > > > > (`port` here is just an alias for `sing`, possibly constrained to only > > construct port singletons.) > > > > --[[Joey]] > > > > A further problem with this is that it's not clear from the > > `virtualHost` type signature that it needs to have a port applied to > > it to get a usable property. So in a way, by adding this advanced > > type safety, we've lost the most fundamental type safety of all: > > Functions must have the right parameters applied! > > > > Well then, let's require a parameter. > > > > virtualHost :: Domain -> WebRoot -> Resource port -> RevertableProperty DebianLike DebianLike > > > > Make `Resource` only able to be constructed by `using`, > > so the user must say: > > > > & virtualHost "example.com" "/var/www" `using` (port :: UsingPort 80) > > > > So the type of `using` would be something like: > > > > using :: (Resource r -> Property proptype) -> r -> Property (r + proptype) > > > > (Complicated some as it needs to also support RevertableProperty.) > > > > --[[Joey]]