Reputation: 968
Using a genome type implemented in a following way
type Genome<'T> (listIn : List<'T>)=
member this.list = listIn
member this.GetValues() =
this.list
I ran into a problem while writing another code fragment.
type IMutation =
abstract member MutateMethod: Genome<'T> -> Genome<'T>
type DoubleGenomeMutation() =
member this.Mutate = (this :> IMutation).MutateMethod
interface IMutation with
member this.MutateMethod(genome: Genome<'T>) =
let randomIndex = MyRandom.Next(0, genome.list.Length)
printfn "%d" randomIndex
let newValue = MyRandom.NextDouble(Parameters.LowerBounds.Item(randomIndex), Parameters.UpperBounds.Item(randomIndex))
let (newGenomeList : List<'double>, _) =
List.foldBack (fun elem acc ->
match acc with
| (l, 0) -> (newValue::l, -1)
| (l, i) -> (elem::l, i-1)) (genome.GetValues()) ([], genome.GetValues().Length - randomIndex - 1)
new Genome<'T>(newGenomeList)
I found it impossible to use the generics mechanism correctly here. The quoted sample effects in
Error 2 Type mismatch. Expecting a
float list
but given a
List<'a>
The type 'float' does not match the type ''a'
in line
| (l, i) -> (elem::l, i-1)) (genome.GetValues()) ([], genome.GetValues().Length - randomIndex - 1)
Casting a variable up or down was ofter described as solution in similar cases - unfortunately I was unable to fix my program this way. I would appreciate any direct help as well as any suggestions about the root of all problems.
Upvotes: 1
Views: 100
Reputation: 29120
I don't have the source of MyRandom
, but if I replace MyRandom.Next
with an int
as it looks like it should be and replace MyRandom.Double
with a double
, then I can reproduce your error.
The problem is that the return type of MyRandom.NextDouble
is constraining the rest of the code inappropriately; MutateMethod
is declared to be able to take any type argument, but then you use the newValue
as part of the return list in the (l, 0)
case which constrains the type of the other case too.
You may also have got a warning from newValue
pointing out that it was constraining your 'double
type variable to be of type float
which is another clue. Really 'double
should be 'T
as that's how the parameter is originally declared.
The error goes away if I replace the call to MyRandom.NextDouble
with throwing an exception (which can have any result type), which confirms this diagnosis:
type DoubleGenomeMutation() =
member this.Mutate = (this :> IMutation).MutateMethod
interface IMutation with
member this.MutateMethod(genome: Genome<'T>) =
let randomIndex = 1 // MyRandom.Next(0, genome.list.Length)
printfn "%d" randomIndex
let newValue = failwith "foo"
let (newGenomeList : List<'T>, _) =
List.foldBack (fun elem acc ->
match acc with
| (l, 0) -> (newValue::l, -1)
| (l, i) -> (elem::l, i-1)) (genome.GetValues()) ([], genome.GetValues().Length - randomIndex - 1)
new Genome<'T>(newGenomeList)
Upvotes: 2