2015-06-02 15 views
13

Mam problem związany z systemem typu Haskell. To nie pierwszy raz, kiedy napotkałem ograniczenia systemu typu. Pominę szczegóły mojego projektu i skorzystam z uproszczonego przykładu. Oto kod:Haskell: Czy zmienne typu mogą być używane w ramach definicji funkcji?

-- Works 
foo :: (Bounded a, Enum a) => a 
foo = minBound 

-- "ambiguous" constraint: 
-- 'a' has no occurrences in type declaration 
bar :: (Bounded a, Enum a) => Int 
bar = fromEnum minBound 

-- Too much information in return 
-- but I can show haskell the appropriate type of 'min' 
baz :: (Bounded a, Enum a) => (a, Int) 
baz = let min = minBound 
    in (min, someFunction . fromEnum $ min) 

-- Type constraint 'a' not ambiguous 
--  (or at least that isn't the compiler error message) 
-- but Haskell doesn't know which 'minBound' to use 
barrer :: (Bounded a, Enum a) => a 
barrer = let min = minBound -- <- min's type is ambiguous 
    in toEnum . someFunction . fromEnum $ min 

Co staram się osiągnąć jest podobna do barrer: Po pierwsze, należy użyć wartości minBound swoiste dla danego typu a i „rzucić” na liczbę całkowitą. W moim projekcie przystąpiłem do przekształcenia tej liczby całkowitej (aby uniknąć pośrednich arytmetycznych przepełnień przy użyciu typu a) i "odrzuć" je ponownie do typu a (po odrobinie magii mod). Jak mogę powiedzieć Haskellowi odpowiedni typ minBound? Czy to możliwe?

Oczywistym rozwiązaniem jest dodanie adnotacji o minBound :: a. Naprawiłoby to również bar. Problem: zmienna typu a wydaje się być poza zakresem definicji funkcji, ponieważ Haskell odświeża minBound :: a do minBound a0 w komunikacie o błędzie. Czy istnieje sposób na wykonanie tego typu adnotacji?

Jednym ze złych hacków, których użyłem, było ograniczenie typu wywołania minBound przez włączenie go do typu zwrotu funkcji, a la baz. To rozwiązanie nie jest idealne. Czy ktoś ma jakieś porady?

Odpowiedz

14

Rozszerzenie ScopedTypeVariables rozwiązuje dokładnie twój problem. Strona zawiera także kilka alternatywnych rozwiązań (argumenty: asTypeOf i undefined).

+0

"Zmienne typu" - Dokładnie to, czego chciałem. I powiedział o wiele bardziej zwięźle niż mój tytuł! – bimmo

+0

Jak zrobiłbyś to z ASTypeOf i undefined? Wydaje mi się, że nigdy nie można uzyskać wartości typu 'a', aby wskazywać asTypeOf w, ponieważ żadna nie jest przekazywana ani zwracana z tej funkcji. Można uzyskać tylko jedną zmienną typu o ograniczonym zasięgu, w którym to momencie nie potrzebujesz już asTypeOf lub undefined. – amalloy

+2

@amalloy Ponieważ 'asTypeOf' nigdy nie ocenia swojego drugiego argumentu, po prostu używa go do wnioskowania o typ, można go powiązać w takie węzły:' 'barrer = let min = minBound' asTypeOf' result; result = toEnum. someFunction. fromEumum $ min in result'' –

Powiązane problemy