LiquidHaskell: пытается использовать ключевое слово предположить, но тип данных не числовой
Я пытаюсь написать некоторые спецификации для Data.Ratio
модуль. Пока что у меня есть:
module spec Data.Ratio where
import GHC.Real
Data.Ratio.denominator :: GHC.Real.Integral a => r : GHC.Real.Ratio a -> {x:a | x > 0}
Код, который я проверяю:
{-@ die :: {v:String | false} -> a @-}
die msg = error msg
main :: IO ()
main = do
let x = 3 % 5
print $ denominator x
if denominator x < 0
then die "bad ending"
else putStrLn "good ending"
Код считается безопасным, потому что знаменатель никогда не возвращает отрицательное значение.
Я нашел это странным, потому что я мог бы просто написать x <= 0
в качестве постусловия, которое согласно документации Data.Ratio
Модуль невозможен. Судя по всему, Liquid Haskell не сравнивает мое постусловие с реализацией denominator
,
Насколько я понимаю, поскольку реализация функции не проверялась, лучше использовать ключевое слово предположить:
assume Data.Ratio.denominator :: GHC.Real.Integral a => r : GHC.Real.Ratio a -> {x:a | x > 0}
Тем не менее, я тогда получаю:
Ошибка: неверная спецификация типа предполагаемый тип GHC.Real.denominator:: (Ratio a) -> {VV: a | VV > 0} Ошибка сортировки при уточнении: {VV: a_a2kc | VV > 0} Несвязанный символ a_a2kc Возможно, вы имели в виду: papp5, papp3, papp4, head, papp2, papp7, papp6, papp1, tail так как Сорт a_a2kc не числовой
Мои вопросы
- Разве ЛГ не должна заставлять меня использовать
assume
ключевое слово в этом случае, если оно явно не проверяет правильность моего уточненного типа по сравнению с реализацией функции? - Правильно ли я думаю, что я должен использовать
assume
ключевое слово? - Как так
a
вдруг не числовой? Разве это не числовой, когда я не использовалassume
?
1 ответ
К сожалению, под "Числовым" оно буквально означает "Num", а не даже его подклассы. Нам нужно расширить LH для поддержки подклассов в форме, которую вы описали выше; Я создам проблему для этого, спасибо за указание!
Теперь, если вы специализируете свой тип, например, Int
или же Integer
тогда LH правильно выдает ошибку:
import GHC.Real
{-@ assume denom :: r:GHC.Real.Ratio Int -> {x:Int | x >= 0} @-}
denom :: GHC.Real.Ratio Int -> Int
denom = denominator
{-@ die :: {v:String | false} -> a @-}
die msg = error msg
main :: IO ()
main = do
let x = 3 % 5
print $ denom x
if denom x <= 0
then die "bad ending"
else putStrLn "good ending"
http://goto.ucsd.edu:8090/index.html
если вы делаете тип вывода x > 0
тогда снова безопасно.
http://goto.ucsd.edu:8090/index.html
Еще раз спасибо за указание на Ratio
Вопрос!