2015-02-26 3 views
0

В последней строке следующего фрагмента кода, я получаю два предупреждения: This construct causes code to be less generic than indicated by the type annotations. The type variable 'c has been constrained to be type ''a'. и This construct causes code to be less generic than indicated by the type annotations. The type variable 'b has been constrained to be type ''a * 'a'.F умозаключение # типа менее общие, чем указано в аннотации типа

type SomeBaseClass<'a>() = 
    class end 

type SomeClass<'a when 'a:equality> (getValue:unit->'a, ?arg2:SomeBaseClass<'b>) = 
    inherit SomeBaseClass<'a*'a>() 

    member this.Value with get() = getValue() 

    member this.Transform (transformation:'a->'c) = 
     let func():'c = transformation this.Value 
     SomeClass<'c> (func, this) // warnings are attached to this line 

Это, с другой стороны, компилирует без проблем:

type SomeOtherClass<'a when 'a:equality> (getValue:unit->'a) = 
    inherit SomeBaseClass<'a*'a>() 

    member this.Value with get() = getValue() 

    member this.Transform (transformation:'a->'c) = 
     let func():'c = transformation this.Value 
     SomeOtherClass<'c> func 

Я не вижу ничего предотвращения transformation от возвращения другого типа, чем он пропускается. Я также не понимаю, почему это второе предупреждение является даже предупреждением, потому что уже очевидно, что для параметра 'b для нового экземпляра явно будет 'a*'a.

Что я здесь делаю неправильно?

ответ

4

Общий тип SomeClass использует общий аргумент 'b в своем конструкторе, отсутствующий в его определении. Изменение определения типа для

type SomeClass<'a, 'b when 'a:equality> ... 

и линия с предупреждением

SomeClass(func, this) 

устраняет ошибку, и возвращаемый класс типа SomeClass<'c, ('a * 'a)>.

Я понятия не имею, чего это пытается достичь, поэтому я не могу сказать, является ли это разумной коррекцией.

+0

Это устраняет предупреждение, но имеет побочный эффект от того, что каждый экземпляр SomeClass имеет два типа параметров вместо одного, который не является дополнительной сложностью, которую я ищу с дополнительным параметром, который не сохраняется как поле экземпляра. Есть ли способ дать конструктору аргумент типа, который сам класс не имеет или мне нужно использовать статическую функцию или что-то вместо этого? – Flaise

+0

@Flaise 'SomeClass' обычно должен иметь два параметра типа, если его конструктор имеет их. Представьте себе выражение типа Array.zeroCreate <'b> 8' где-то в типе; его результат не будет правильно определен в системе типов F # без аргумента второго типа. Но точный тип 'SomeClass' часто можно вывести. Я отредактировал ответ, так что он опускает аргументы типа в вызове конструктора. Конечно, это менее вероятно, если один из параметров является необязательным; второй тип должен быть ясен из другого контекста, чем конструктор. – Vandroiy

+0

Так что я не могу параметризовать/просто/конструктор - конструктор принимает те же аргументы типа, что и весь класс? Я просто использую статическую функцию, так как .NET сохраняет информацию о типе во время выполнения, что мешает отладке и производительности. – Flaise

Смежные вопросы