2012-10-29 18 views
5

Piszę bibliotekę do obliczeń geodezyjnych. Jedną rzeczą, którą chcę uwzględnić, jest typ do rzutowania siatki (na przykład Krajowa siatka badania Ordnance Survey) i punkty na tych siatkach (określone przez "wschody" i "północy"). Siatka jest określona przez punkt początkowy, który wiąże ją z Ziemią i wiązkę parametrów geometrycznych. Programista aplikacji może tworzyć wiele arbitralnych sieci przy użyciu tych parametrów. Pojawi się także szereg rodzajów sieci bazujących na różnych projekcjach podstawowych.Jak używać typów do rozdzielania niezgodnych wartości

Oczywiście chcę mieć możliwość wykonywania obliczeń na punktach siatki (np. Odległość, łożysko itp.), , ale jednocześnie chcę użyć systemu typu Haskell, aby uniemożliwić programistom żądanie odległości między dwoma punkty na różnych siatkach. Zastanawiałem się, czy Monada Reader używająca parametru typu wzdłuż linii monady ST będzie działała, ale chcę, żeby programista mógł przechowywać te wartości pozycji poza monadą, podczas gdy ST chodzi o zapobieganie przeciekom z STRefs. runST.

Mam również podobny problem z położeniami geodezyjnymi (szerokość geograficzna & długości geograficznej) na leżących poniżej elipsoidach. Ale wersja siatkowa jest prawdopodobnie łatwiejsza do wytłumaczenia, zważywszy, że głównym tematem tego pytania jest system typu, a nie geodetyka.

Czytałem o GADT i typach egzystencjalnych, ale nie widzę, jak to zrobić.

+0

Może to być sposób na arytmetykę typu: http://www.haskell.org/haskellwiki/Type_arithmetic – Wes

+0

"ale jednocześnie chcę użyć systemu typu Haskell, aby uniemożliwić programistom żądanie pytania odległość między dwoma punktami na różnych siatkach "- dlaczego tak jest? Punkty mogą być zdefiniowane na różnych siatkach i nadal reprezentują tę samą lokalizację _physical_, dlaczego nie chcesz pozwolić na obliczenie odległości między takimi punktami? – leftaroundabout

+0

@leftaroundabout: tak, ale to wymaga transformacji współrzędnych i bardziej złożonych obliczeń. Również w niektórych przypadkach proste obliczenia planarne są właściwe (np. W przypadku radarów). –

Odpowiedz

2

Można użyć dwóch rozszerzeń GHC, co pozwala oznaczyć koordynuje z siatki, z którego pochodzą: (. Rozszerzenia pracować w GHC 7.4+, nie wiedząc o niczym niższym)

{-# LANGUAGE DataKinds, KindSignatures #-} 

data CoordinateType = Geodetic | OSNG -- etc. 

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

zeroZero :: Coordinate Geodetic 
zeroZero = Coord 0 0 

następnie wszelkie funkcje wymagające go może wymusić równość parametru grid phantom:

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

teraz distance zeroZero (Coord 1 2 :: Coordinate OSNG) daje błąd typu.

+0

Jeśli rozumiem to poprawnie, działa to tylko dla zakodowanej listy wartości CoordinateType (co faktycznie już zrobiłem przy użyciu klas typów, choć bardziej gadatliwy). Chcę powiedzieć coś w rodzaju "data CoordType = Grid Double Double", więc "foo = Grid 3 4; bar = Grid 2 4.2" pozwala mi rozróżniać współrzędne w "foo" od współrzędnych w "barze" na poziomie typu. –

+0

@PaulJohnson, nie jesteś ograniczony do zakodowanej listy wartości, ponieważ (teraz wymaga GHC 7.6) możesz używać łańcuchów i znaków naturalnych na poziomie typu ("promowane literały"). Dokumentacja dotycząca danych -> rodzaj promocji jest [tutaj] (http://www.haskell.org/ghc/docs/7.6.1/html/users_guide/promotion.html), możesz zobaczyć, czy któraś z nich pomaga. – huon

+0

Ale one również muszą być literałami: nie mogę (o ile widzę) czytać ciągu z pliku i promować go do typu. –

Powiązane problemy