8

Napisałem moduł matematyczny Vector w języku Haskell.Haskell typ danych nazywanie pseudonimem

Więc zacząłem się z:

data Vector a = Vector !a !a !a deriving (Eq, Show) 

Precyzyjna to pozwala mi użyć dowolnego typu danych liczbowych chcę. Problem polega na tym, że nie chcę pisać wszędzie ze względu na prostą przyczynę, dla której nie powinienem tego robić. Więc dodam:

type Scalar = Double 
type Vector = Vector Scalar 

Ale oczywiście, że druga linia jest źle, ponieważ nie istnieją obecnie dwie deklaracje Vector. Więc do czego mam to zmienić? Myślę sobie, nie, zamierzam pisać to na całym moim kodzie, więc chcę zostawić alias typu po prostu jako Vector. Co oznacza, że ​​muszę zmienić nazwę typu danych. Ale jeśli to zmienię, to czuję, że powinienem również zmienić konstruktora, co sprawia, że ​​wszystko jest bardziej zagmatwane. Ale jeśli czujesz się niezręcznie, konstruktor ma taką samą nazwę jak alias typu w ten sposób.

Teraz mam to:

type Scalar = Double 
type Vector = VectorT Scalar 

data VectorT a = Vector !a !a !a deriving (Eq, Show) 

Wybrałem T arbitralnie (myślę, że to oznacza „typ”), ale nie jestem tego pewien. Zwykle, gdy dokumentuję funkcje, powiedziałbym: -- Calculate the magnitude of a Vector, ale z VectorT mam wrażenie, że powinienem naprawdę używać nazwy typu , która to nazwa to. W związku z tym odwołuję się do nich jako vectors (bez wielkich liter), z tym wyjątkiem, że muszę zastosować tę konwencję do każdego komentarza dla każdego typu danych.

Czy ktoś był w podobnej sytuacji? Czy w tym przypadku ktoś może pomyśleć o bardziej eleganckim rozwiązaniu?

+0

Widziałem to kilka razy, w szczególności pakiet 'language-c' używa tego podejścia do definiowania reprezentacji drzewa składni. Jeśli nigdy nie spotkałeś się z tym stylem, zanim poczujesz się trochę niezręcznie, ale oczekuję, że ludzie szybko się do niego przyzwyczają. –

+6

Istnieją tylko dwie trudne rzeczy w informatyce: unieważnianie pamięci podręcznej i nazywanie rzeczy. - Phil Karlton –

+2

Może "VectorOf Double", jeśli nie podoba ci się 'VectorT'. – kennytm

Odpowiedz

8

Jednym ze sposobów rozwiązania konkretnego problemu jest posiadanie typu danych w innym module niż synonim typu. To znaczy, że ma moduł Math.Vector, który zawiera deklarację danych i niektóre funkcje ogólne (to jest funkcje działające dla wszystkich typów liczbowych). Wtedy, kiedy faktycznie korzysta Vector Double w kodzie dużo, wystarczy utworzyć typ synonim za pomocą wykwalifikowanego import:

import qualified Math.Vector as MV 

type Scalar = Double 
type Vector = MV.Vector Scalar 

myślę, że to ma sens z punktu widzenia organizacji kodu. W szczególności, jeśli zdefiniowałeś swój typ Vector, aby działał na wszystkich typach liczbowych, oczekuję, że funkcje w tym module będą działać również na wszystkich typach liczbowych. Fakt, że używasz Vector Double dużo w innej części kodu, nie powinien mieć wpływu na moduł, w którym faktycznie zdefiniowano Vector. W końcu całkiem rozsądnie jest wyobrazić sobie używanie numeru Vector Int w jeszcze innej części programu.

Odkładając na bok, nie jestem pewien dzwoniąc pod numer Vector to najlepszy pomysł. Wektor niekoniecznie musi mieć trzy wymiary, więc nazwałbym twój typ danych podobnie jak Vector3D. Jest to nazwa używana w niektórych innych interfejsach API (takich jak Java 3D API), więc jest to prawdopodobnie dobry wybór.

2

Czy jest jakiś konkretny powód, aby nie tylko zrobić

data Vector = Vector !Double !Double !Double deriving (Eq, Show) 

to wydaje się najprostszym pomysłu do mnie ...

+0

Ma to tę zaletę, że '' - # UNPACK # -} 'jest również w stanie. – FunctorSalad

+0

Wtedy nie mogę uczynić go instancją 'Functor' i' Applicative'. – mk12

+0

Przydaje się możliwość "fmap" na dowolnym obrazie - jeśli nic innego, to nie ułatwia implementacji modułu. – mk12