Using bouncy castle v.1.0.1 which is written in C# I'm having issues with type inference. The C# code has a lot of inheritance and interface usage.
// Definitions
public interface IParameters<out TAlg> where TAlg: Algorithm { ... }
public abstract class SignatureParameters<TParam, TAlg, DAlg> : Parameters<TAlg>, ISignatureParameters<TParam, TAlg, DAlg>
where TParam : IParameters<TAlg>
where TAlg : Algorithm
where DAlg : DigestAlgorithm {}
// SignatureFactory interface
public interface ISignatureFactoryService
{
ISignatureFactory<A> CreateSignatureFactory<A>(A algorithmDetails) where A : IParameters<Algorithm>;
}
// SignatureFactory creation
public class SomeClass : ISignatureFactoryService
{
public ISignatureFactory<A> CreateSignatureFactory<A>(A algorithmDetails) where A : IParameters<Algorithm>
{
...
return (ISignatureFactory<A>)new SignatureFactory<Fips.FipsEC.SignatureParameters>(algorithmDetails as Fips.FipsEC.SignatureParameters, new Fips.FipsEC.SignerProvider(algorithmDetails as Fips.FipsEC.SignatureParameters, privateKey));
}
}
Now when I use the library from F# the compiler shows issues because it can not resolve/map IParameters<Algorithm>
to FipsEC.SignatureParameters
// usage F#
let vKey = ... // is AsymmetricECPrivateKey
let signatureFactoryProvider = CryptoServicesRegistrar.CreateService(vKey, new SecureRandom())
let sigParams = FipsEC.Dsa.WithDigest(FipsShs.Sha256)
// sigParam will be of type FipsEC.SignatureParameters
let sigFactry = signatureFactoryProvider.CreateSignatureFactory(sigParams)
// error, FS0001: The type 'FipsEC.SignatureParameters' is not compatible with the type 'IParameters<Algorithm>'
FipsEC.SignatureParameters
is defined as
public class SignatureParameters: SignatureParameters<SignatureParameters, FipsAlgorithm, FipsDigestAlgorithm>
{
internal SignatureParameters(FipsAlgorithm algorithm, FipsDigestAlgorithm digestAlgorithm): base(algorithm, digestAlgorithm)
{
}
internal override SignatureParameters CreateParameter(FipsAlgorithm algorithm, FipsDigestAlgorithm digestAlgorithm)
{
return new SignatureParameters (algorithm, digestAlgorithm);
}
}
I tried to define the right type but obviously this is not doing anything
let sigParams = IParameters<Algorithm> = FipsEC.Dsa.WithDigest(FipsShs.Sha256)
// error FS0001: this expression was expected to have type 'IParameters<Algorithm>' but here has type 'FipsEC.SignatureParameters' which itself is again Parameters<TAlg>, ISignatureParameters<TParam, TAlg, DAlg> (see above), so it should work...
Question now is, how can I help the compiler? I have tried to cast it, but without luck.
There is no implicit cast in F# (with exception for obj
), so you have to either explicitly cast to interface, or to use flexible types:
1. Explicit cast:
upcast
operator:let sigParams : IParameters<Algorithm> = upcast FipsEC.Dsa.WithDigest(FipsShs.Sha256)
:>
) operator:let sigParams = FipsEC.Dsa.WithDigest(FipsShs.Sha256) :> IParameters<Algorithm>
2. Flexible types (note the #
sign before interface type):
let sigParams : #IParameters<Algorithm> = FipsEC.Dsa.WithDigest(FipsShs.Sha256)
The second one is especially useful in function definitions:
let doSomethingWithParameters<'a> (params: #IParameters<'a>) = // some action here
// ...
// usage of the defined above function:
FipsEC.Dsa.WithDigest(FipsShs.Sha256)
|> doSomethingWithParameters
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.