Hello,
I have written a property to create a Mysql user which take the password from privdata. Now, I need to generate many passwords for several PHP sites, so I wrote a function to generate password using a hash of a secret salt and information from the context (site name). This password will be written in a .php file to configure the application.
I added a function Mysql.userGrantedOnDatabaseWithPassword
, so that I can give
it the computed password and use a common function to return the property.
The problem is that when using privdata, the common function should return a:
ReversibleProperty (HasInfo + DebianLike) UnixLike
And when not using privdata, it should return a:
ReversibleProperty DebianLike UnixLike
The function takes a parameter to handle the password retrieval (i
is (HasInfo
+ DebianLike)
or DebianLike
):
((((String -> Propellor Result) -> Propellor Result) -> Property i) -> Property i)
This is a type similar to withPrivData
, but adapted to give just the
password:
-- | Common code to get password from private data.
withPasswordFromPrivData
:: IsContext c
=> User
-> c
-> ((((String -> Propellor Result) -> Propellor Result)
-> Property (HasInfo + UnixLike))
-> Property (HasInfo + UnixLike))
withPasswordFromPrivData (User username) context = \mkprop ->
withPrivData (Password username) context
$ \getdata -> mkprop
$ \a -> getdata $ \priv -> a $ privDataVal priv
-- | Common code to pass password from parameter.
withPasswordFromParameter
:: String
-> ((((String -> Propellor Result) -> Propellor Result)
-> Property UnixLike) -> Property UnixLike)
withPasswordFromParameter password = \mkprop ->
mkprop $ \a -> a password
I do not find a way to write the type of my function with the common code, the current best is:
userGrantedProp
:: Combines (Property i) (Property UnixLike)
=> User
-> [Privilege]
-> ((((String -> Propellor Result) -> Propellor Result)
-> Property i) -> Property i)
-> String
-> (String -> String -> String -> String)
-> (String -> String -> String -> String)
-> RevertableProperty (CombinedType (Property i) (Property UnixLike)) UnixLike
userGrantedProp (User username) privs withPassword setupDesc setupSql userGrants =
But it still does not compile.
The full code is available on my mysql-wip
branch on
http://git.ni.fr.eu.org/nicolas/propellor.git
, I would be glad if you can have
a look, pure haskell fun guaranteed :-).
Thanks.
Building that, the first error message is this:
It's really complaining that it expected HasInfo + DebianLike and got HasInfo + UnixLike; ie your property seems to also support ArchLinux and FreeBSD. (Whether it really does, I don't know.)
There seem to be several similar errors in the supported OS's, which don't help with focusing on the other errors..
I have not found a solution to all of those, but part of the problem is that, inside a where clause a type annotation with a type variable such as
i
is not understood to refer to the same variable in the outer type annotation. There's some ghc extension that enables that, but I can never remember its name.After removing those inner type annotations, the remaining type error was with userGrantedProp.. So I removed its type annotation as well and let ghc infer its type. (Had to enable LANGUAGE TypeFamilies for it to be able to.) Here's what ghc thinks it is:
That's not very human friendly a way to write its type, but it gives some good direction. Note in particular that the type of withPassword seems to involve two different types of Property, not the single
Property i
that your original type uses in both places.I have a feeling though that there may be a bug in the code around withPassword that is leading to this type and that the type error is not really the root problem.
Thanks for the analysis.
My
withPassword
parameter can actually have two different types, depending on whether it gets password from privdata or not.Most of my problems when writing complex properties are due to the Property kind, may be I should write simpler properties