2014-09-09 3 views
1

Скажем, у меня есть ДусЛучшие значения по умолчанию для данного типа

type Zero = Zero 
type Succ<'a> = Succ of 'a 

я могу использовать Unchecked.defaultof<Zero Succ Succ>, когда я передаю значение для встроенной функции, которая использует только тип этого значения. Но как я могу получить правильное значение данного типа? Тот, который не является нулевым.

Поскольку единственное допустимое значение, которое имеет тип Zero Succ Succ, равно Succ(Succ(Zero)) Я чувствую, что смогу его получить.

Я не забочусь о безопасности промежуточного типа, поэтому я в порядке с типами.

Я попытался это:

let rec makeProperSucc (a : Succ<'a>) = Succ(makeProperNum Unchecked.defaultof<'a>) 

and makeProperNum (obj : obj) : obj = 
    if obj :? Zero then Zero :> obj 
    else makeProperSucc (obj :?> Succ<obj>) :> obj 

let instance<'a>() = makeProperNum Unchecked.defaultof<'a> :?> 'a 

Который не работает, потому что defaultof дает мне пустую и всю информацию типа теряется, потому что я посылаю его к функции ожидающего OBJ.

ответ

3

Как определить статический член со статическими ограничениями в DU?

Вот быстрый проект с унарным:

type Zero = Zero with 
    static member (!!) Zero = Zero 

type Succ<'a> = Succ of 'a with 
    static member inline (!!) (Succ a) = Succ (!!a) 

// Test 
!!(Unchecked.defaultof<Succ<Succ<Succ<Zero>>>>) 
// val it : Succ<Succ<Succ<Zero>>> = Succ (Succ (Succ Zero)) 

Я использовал оператор, чтобы сохранить его простым, но вы также можете написать статические ограничения вручную или использовать inline helper, как вы делали раньше в ваших previous question ,

UPDATE

Если вы хотите использовать модуль inline helper, используемый в FsControl 1.x, вы можете сделать это следующим образом:

type Instance = Instance with 
    static member  instance(Instance, _:unit ) = fun() ->() 
    static member  instance(Instance, _:Zero ) = fun() -> Zero 
    static member inline instance(Instance, _:Succ<'b>) = fun() -> 
     Succ (Inline.instance Instance()) 

let inline instance() = Inline.instance Instance() 

let test:Succ<Succ<Zero>> = instance() 

Если вы хотите использовать обозначение instance<'t>() вы придется отключить предупреждение.

+0

Ну, я пробовал с встроенным помощником, но не смог его решить. Я не совсем понимаю, что именно делает возможным или невозможным вывести тип. Спасибо за ответ, как обычно. –

+0

Не беспокойтесь, это хорошая забава, см. Обновление. – Gustavo

+0

Отлично! Ну, вот моя попытка, если вы, возможно, захотите увидеть, где я перепутал http://pastebin.com/QqCTcg5Z Почему явная передача оставшегося типа не позволяет его решить? –

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