Подтвердить что ты не робот

Haskell: Можно ли использовать переменные типа в определении функции?

У меня проблема с системой типа Haskell. Это не первый раз, когда я сталкивался с ограничениями системы типов. Я опускаю детали своего проекта и использую упрощенный пример. Вот какой код:

-- 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 type is ambiguous
    in toEnum . someFunction . fromEnum $ min

То, что я пытаюсь достичь, похоже на barrer: во-первых, используйте значение minBound, соответствующее типу a и 'cast' его целому числу. В моем проекте я перехожу к преобразованию этого целого числа (чтобы избежать промежуточных арифметических переполнений при использовании типа a) и "отбросить" их обратно, чтобы напечатать a (после немного магии mod). Как я могу указать Haskell на соответствующий тип minBound? Возможно ли это?

Очевидным решением является добавление аннотации minBound :: a. Это также исправило бы bar. Проблема: переменная типа a, по-видимому, выходит за рамки определения функции, так как Haskell освещает minBound :: a до minBound a0 в сообщении об ошибке. Есть ли способ сделать этот тип аннотации?

Один плохой хак, который я использовал, заключался в том, чтобы ограничить тип вызова minBound, включив его в возвращаемый тип функции, a la baz. Это решение не является идеальным. Есть ли у кого-нибудь советы?

4b9b3361

Ответ 1

Расширение ScopedTypeVariables решает именно вашу проблему. На странице также представлены некоторые альтернативные решения (аргументы asTypeOf и undefined).