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?
"Zmienne typu" - Dokładnie to, czego chciałem. I powiedział o wiele bardziej zwięźle niż mój tytuł! – bimmo
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
@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'' –