2012-10-29 14 views
5

Ich schreibe eine Bibliothek für geodätische Berechnungen. Eine Sache, die ich einbeziehen möchte, ist ein Typ für Rasterprojektionen (z. B. Ordnance Survey National Grid) und Punkte auf diesen Rastern (angegeben durch "eastings" und "northings"). Ein Gitter wird durch einen Ursprungspunkt, der es mit der Erde verbindet, und durch eine Menge geometrischer Parameter spezifiziert. Der Anwendungsprogrammierer kann mithilfe dieser Parameter viele beliebige Raster erstellen. Es wird auch eine Reihe von Gittertypen geben, die auf verschiedenen zugrunde liegenden Projektionen basieren.Wie verwende ich Typen, um inkompatible Werte zu trennen

Offensichtlich möchte ich in der Lage sein, Berechnungen auf Rasterpunkten (zB Entfernung, Peilung usw.), zu machen, aber gleichzeitig möchte ich das Haskell-System verwenden, um zu verhindern, dass ein Anwendungsprogrammierer nach dem Abstand zwischen zwei fragt Punkte auf verschiedenen Gittern. Ich fragte mich, ob ein Reader Monad, der einen Typparameter entlang der ST-Monade verwendet, funktionieren würde, aber ich möchte, dass der Anwendungsprogrammierer diese Positionswerte außerhalb der Monade speichern kann, während es bei ST darum geht, das Lecken von STRefs zu verhindern das runST.

Ich habe auch ein ähnliches Problem mit geodätischen Positionen (Breitengrad & Länge) auf den zugrunde liegenden Ellipsoiden. Aber die Grid-Version ist wahrscheinlich leichter zu erklären, da der Schwerpunkt dieser Frage eher auf dem Typensystem als auf Geodäten liegt.

Ich habe GADTs und existentielle Typen gelesen, aber ich kann nicht sehen, wie man das macht.

+0

Könnte ein Weg sein, dies mit arithmetischen Typ zu tun: http://www.haskell.org/haskellwiki/Type_arithmetic – Wes

+0

"aber gleichzeitig möchte ich das Haskell-Typ-System verwenden, um zu verhindern, dass ein Anwendungsprogrammierer fragt der Abstand zwischen zwei Punkten auf verschiedenen Gittern "- warum ist das? Punkte können auf verschiedenen Gittern definiert werden und stellen immer noch den gleichen physikalischen Ort dar. Warum sollten Sie nicht die Entfernung zwischen diesen Punkten berechnen lassen? – leftaroundabout

+0

@leftaroundabout: Ja, aber das erfordert eine Koordinatentransformation und komplexere Berechnungen. Auch in einigen Fällen ist die einfache planare Berechnung die richtige Sache (z. B. wenn es sich um Radare handelt). –

Antwort

2

können Sie zwei GHC-Erweiterungen verwenden, damit Sie Koordinaten mit dem Raster markieren sie kommen: (. Die Erweiterungen arbeiten in GHC 7.4+, nicht sicher etwas niedriger)

{-# LANGUAGE DataKinds, KindSignatures #-} 

data CoordinateType = Geodetic | OSNG -- etc. 

data Coordinate (grid :: CoordinateType) = Coord Int Int 

zeroZero :: Coordinate Geodetic 
zeroZero = Coord 0 0 

dann benötigen alle Funktionen kann es Gleichheit der grid Phantom Parameter erzwingen:

distance :: Coordinate grid -> Coordinate grid -> Float 
distance p q = undefined 

Jetzt distance zeroZero (Coord 1 2 :: Coordinate OSNG) gibt einen Typfehler.

+0

Wenn ich das richtig verstehe, funktioniert es nur für eine fest codierte Liste von CoordinateType-Werten (die ich tatsächlich schon mit Typklassen gemacht habe, wenn auch ausführlicher). Ich möchte etwas wie "Daten CoordType = Grid Double Double" sagen, so dass "foo = Grid 3 4; bar = Grid 2 4.2" erlaubt, Koordinaten in "foo" von Koordinaten in "bar" auf der Typ-Ebene zu unterscheiden. –

+0

@PaulJohnson, Sie sind nicht auf eine hart codierte Liste von Werten beschränkt, weil (jetzt GHC 7 erforderlich.6) Sie können Strings und Naturals auf der Typ-Ebene ("Promited Literals") verwenden. Die Dokumentation über die Daten -> Artpromotion ist [hier] (http://www.haskell.org/ghc/docs/7.6.1/html/users_guide/promotion.html), man könnte sehen, ob irgendetwas davon hilft. – huon

+0

Aber sie müssen auch Literale sein: Ich kann (so weit ich das sehe) nicht in einer Zeichenkette aus einer Datei lesen und diese zu einem Typ hochstufen. –

Verwandte Themen