2010-08-27 16 views
7

Programistów Ocaml można używać tak zwanych "typów fantomów" do wymuszania pewnych ograniczeń za pomocą systemu typów. Dobry przykład można znaleźć pod adresem http://ocaml.janestreet.com/?q=node/11.Implementowanie typów fantomowych w języku F #

Składnia type readonly nie działa w języku F #. Można go zastąpić pseudofantycznym typem zdefiniowanym jako type readonly = ReadOnlyDummyValue w celu implementacji sztuczek we wspomnianym blogu.

Czy istnieje lepszy sposób definiowania typów fantomów w F #?

+4

Czy znasz http://blog.matthewdoig.com/?p=134 i http://blog.matthewdoig.com/?p=138? –

+0

Dzięki za linki. Jakoś tęskniłem za nimi. –

+1

Blog matthewdoiga jest martwy, ale artykuły znajdują się na archive.org: http://web.archive.org/web/20100615031828/http://blog.matthewdoig.com/?p=134 http: //web.archive .org/web/20100615031841/http: //blog.matthewdoig.com/? p = 138 –

Odpowiedz

14

Myślę, że definiowanie typu tylko przy użyciu type somename nie będzie działać w F #. Kompilator F # musi wygenerować pewien typ .NET z deklaracji, a specyfikacja F # nie definiuje jednoznacznie, co powinno się stać w przypadku typów fantomowych.

Można utworzyć typ betonu (np. Z type somename = ReadOnlyDummyValue) w pliku implementacji (.fs) i ukryć elementy wewnętrzne typu, dodając tylko type somename do pliku interfejsu (.fsi). W ten sposób stajesz się bliski typowi widma - użytkownik spoza tego pliku nie zobaczy wewnętrznych elementów tego typu.

Inną interesującą alternatywą byłoby użycie interfejsów. Brzmi to dla mnie logicznie, ponieważ pusty interfejs jest prawdopodobnie najprostszym typem, który można zadeklarować (i nie wprowadza żadnych fałszywych identyfikatorów). Pusty interfejs wygląda tak:

type CanRead = interface end 
type CanWrote = interface end 

Co ciekawe, w tym przypadku, jest to, że można również tworzyć odziedziczone interfejsy:

type CanReadWrite = 
    inherit CanRead 
    inherit CanWrite 

Następnie można napisać funkcję, która może przyjmować wartości typu Ref<CanRead, int> ale także wartości typu Ref<CanReadWrite, int> (ponieważ wartości te obsługują również odczyt):

let foo (arg:Ref<#CanRead, int>) = // ...  

To wydaje się jak coś, które mogłyby być u seful. Byłbym całkiem zainteresowany, czy można to zrobić również w OCaml (ponieważ opiera się na obsłudze F # dla interfejsów i dziedziczenia).

+0

Sugestia użycia interfejsów jest świetna. Dzięki! –

+0

@ Tomas: Oczywiście można to zrobić również w OCaml. –

+0

@Jon: Spodziewałem się tego. Po prostu nie wiedziałem jak i nie mogłem znaleźć żadnego dobrego źródła informacji. Czy masz link do jakiegoś przykładu (najlepiej swobodnie dostępny ;-))? –

Powiązane problemy