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 не числовой

Мои вопросы

  1. Разве ЛГ не должна заставлять меня использовать assume ключевое слово в этом случае, если оно явно не проверяет правильность моего уточненного типа по сравнению с реализацией функции?
  2. Правильно ли я думаю, что я должен использовать assume ключевое слово?
  3. Как так 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 Вопрос!

Другие вопросы по тегам