Jelen kontextusban ontológián egy speciális tudásábrázolási technikát értek. Egy közismert definíció szerint „az ontológia egy közös fogalomrendszer formális, explicit specifikációja”
Egy ontológia készítését a forrásanyagok kiválasztása előzi meg. Az F# nyelv esetén elsődleges forrásnak a – draft státuszú – specifikációt tekintettem. Először megpróbáltam elkészíteni a nyelv ontológiáját csak a vázlatos szabványra hivatkozva, de nem sikerült. Egyrészt a dokumentum egy egyszerű taxonómia készítéséhez sem tartalmaz elegendő mennyiségű és minőségű információt. Másrészt a fő hangsúlyt a nyelv szintaktikájára helyezi, miközben elhanyagolja a fontos F# fogalmak definícióját. A kifejezéseket gyakran nem kíséri magyarázat, olykor pedig több jelentésük is ismert. Mivel az F# draft specifikáció elégtelennek bizonyult, más megbízható forrást kellett keresnem. Választásom két szakkönyvre esett: Foundations of F# és Expert F#. Ezek a források azért tekinthetők megbízhatónak, mert szerzőik a nyelv tervezői és olyan személyek, akik szoros kapcsolatban állnak a nyelv fejlesztésével. Az így feldolgozott korpusz mennyisége összesítve 1156 nyomtatott oldal.
A fogalmakat két ontológiába csoportosítottam:
Az F# a „típus” kifejezést négy különböző, ugyanakkor kapcsolódó értelemben használja. Az ontológiakészítés szempontjából ezen jelentések pontos szétválasztása lényegbevágó. A négy jelentés a következő:
Az F# típusok elemzésénél végig a statikus típusokra támaszkodom. A dolgozat további részében a „típus” kifejezésen a statikus típusokat értem.
Az ontológia készítése során az egyik legjelentősebb problémám az volt, hogy milyen elvek mentén csoportosítsam az F# típusokat. Felmerült például a funkcionális-imperatív, mutable-immutable, referenciatípus-értéktípus stb. csoportosítás. Mindegyik választással az a probléma, hogy a többi csoportosítás alapját képező tulajdonságokat is fel kell tüntetni a diagramon úgy, hogy az pontos legyen, de ugyanakkor átlátható maradjon. Kezdetben a Pickering által javasolt csoportosítás tűnt vonzónak:
The type system in F# provides a number of features for defining custom types. All of F#’s type definitions fall into two categories. The first category is types that are tuples or records. These are a set of types composed to form a composite type (similar to structs in C or classes in C#). The second category is sum types, sometimes referred to as union types. (p. 42)
Pickering szerint tehát az F# típusok alapvetően két csoportra oszthatók, az első kategóriába a tuple vagy rekord típus kerül, míg a másik csoportba az ún. szum típusok tartoznak, amit gyakran union típusnak is neveznek.
Ennek a megközelítésnek a legnagyobb hátránya, hogy nem ragadja meg a struct, union és record típusok közötti erőteljes hasonlóságot. Az említett típusok mindegyikének lehetnek tagjai (tulajdonságok és metódusok), implementálhatnak interfészeket és zártak (sealed), azaz nem specializálhatók. A közös vonások kiemelése érdekében bevezettem egy közös őst, az osztályszerű típust (class-like type), ami azt a tényt is tükrözi, hogy a struct kivételével ezek a típusok .NET osztály típusra fordítódnak.
Végül úgy döntöttem, az F# típusokat két nézet szerint csoportosítom. Az egyik a típusok szerkezetén, a másik az értéktípus-referenciatípus megkülönböztetésen alapszik.
A .NET típusokat zöld háttérrel jelöltem. Ezeket nem fejtem ki a diagramon, részletekért lásd a .NET CLS ontológiát. MEGJEGYZÉS. Az F# osztálytípus a CLS objektumtípus megfelelője.
1. diagram. F# típusok ontológiája, szerkezeti nézet
Az áttekinthetőség kedvéért a Lista (List) típust külön diagramon mutatom be:
2. diagram. Az F# Lista típusa (az F# típusok ontológiájának részlete)
1. táblázat. Az F# típusok ontológia fogalmai
2. táblázat. Az F# típusok ontológia kapcsolatai
Megszorítások
Inkonzisztenciák
Ennél a nézetnél csak a diagramot ismertetem, mivel új fogalmakat nem vezet be. Az F# három értéktípust ismer, ezek az előredefiniált értéktípusok (pl. int, boolean stb.), az enumok és a struktúrák. Az összes többi típus a referenciatípusok közé sorolható.
3. diagram. Az F# típusok ontológiája, érték-referencia nézet
Inkonzisztenciák
Értéktípus vs. struct típus. Az F# draft az int típust struct típusnak tekinti: „we say int is a struct type because System.Int32 is a struct type.”. Az ECMA-335 nem említi a struct kifejezést az értéktípus szinonimájaként, a System.Int32-t a beépített értéktípusok között tartja számon. Az ECMA terminológia jellemzően az értéktípus kifejezést használja, míg az F# szakirodalom a struct (struktúra) szinonimával illeti az érték típusú szerkezeteket. Ezzel az a probléma, hogy a struct egyben a C-ből közismert rekord- szerű szerkezet elnevezése is egyben, ez pedig néhol félreértéshez vezethet. Javaslom, hogy a struct kifejezést az utóbbi értelemben használjuk.
A generikusokat F#-ban a típusváltozók jelképezik, melyek típusa kezdetben változó típus. A változótípusokra típusmegszorításokat alkalmazhatunk, melyek szűkítik a típusváltozó lehetséges értékeit. Az 4. diagram a típuskövetkeztetésnél használatos megszorításokat ábrázolja. A .NET kompatibilitás érdekében bevezetett megszorításokat zöld színnel jelöltem, a sárga hátterűek ritkán használatosak, az egyetlen tényleges használt megszorítás az altípus megszorítás, amit külön színnel emeltem ki. Az ábra jól mutatja, milyen kompromisszumokat kellett kötni a .NET interoperabilitás érdekében.
4. diagram. F# típusváltozó megszorítások
3. táblázat. F# típusváltozó megszorítás fogalmai
MEGJEGYZÉS. A megszorítások között csak öröklődési kapcsolat áll fenn, ezeket az ábra tartalmazza, így további táblázatra nincs szükség.
Inkonzisztenciák
A struct kifejezés további félrevezető használata. Az F# draft korábbi szakasza által említett .NET Struct Constraint megszorítás akkor áll fenn, ha a típus, amelyikre vonatkozik, .NET értéktípus. Az jelent problémát, hogy a CTS nem definiálja a struct típust. Egyértelmű, hogy mivel a referenciatípussal van szembe állítva, itt az értéktípus értelemben használatos, a struct mégsem érvényes CTS típus.