私は Liquid-Haskell を使ってどんな種類のきちんとしたことができるかを確認するためにいくつかの実験を行っていますが、ちょっとした壁にぶつかりました。基本的な考え方は、一定の時間が経過すると有効期限が切れるアクセス トークンを必要とする関数がいくつかあるということです。トークンを関数の 1 つに渡す前に、トークンの有効性を確認するために、liquid-haskell を使用する方法を確認しようとしています。私の問題を示す最小限の作業バージョンを以下に作成しました。このファイルで Liquid を実行すると、次のエラーが発生します。
/tmp/liquidTest.hs:18:17-42: Error: Liquid Type Mismatch
18 | isExpired tok = currTime >= expiration tok
^^^^^^^^^^^^^^^^^^^^^^^^^^
Inferred type
VV : {VV : GHC.Types.Bool | Prop VV <=> Main.currTime >= ?a}
not a subtype of Required type
VV : {VV : GHC.Types.Bool | Prop VV <=> currTime >= expiration tok}
In Context
Main.currTime := Data.Time.Clock.UTC.UTCTime
tok := Main.Token
?a := {?a : Data.Time.Clock.UTC.UTCTime | ?a == expiration tok}
なぜこのエラーが表示され、私が試したすべてが失敗したのか理解できないようです。誰か助けてくれませんか?
また、time パッケージの currTime 関数を getCurrentTime 関数に置き換えたいと考えています。そうすれば、トークンのタイムスタンプを現在の時刻と比較できます。つまり、私の isExpired 関数のタイプは Token -> IO Bool になります。液体ハスケルを使用してもそれは可能でしょうか?
import Data.Time
import Language.Haskell.Liquid.Prelude
{-@ data Token = Token
(expiration :: UTCTime)
@-}
data Token = Token
{ expiration :: UTCTime
} deriving Show
{-@ measure currTime :: UTCTime @-}
currTime :: UTCTime
currTime = UTCTime (ModifiedJulianDay 57614) 83924.978297
{-@ isExpired :: t:Token -> {v:Bool | ((Prop v) <=> (currTime >= expiration t))} @-}
isExpired :: Token -> Bool
isExpired tok = currTime >= expiration tok
{-@ type ValidToken = {t:Token | currTime < expiration t} @-}
{-@ showToken :: ValidToken -> String @-}
showToken :: Token -> String
showToken tok = show tok
main :: IO ()
main = do
ct <- getCurrentTime
let tok = Token ct
print currTime
case isExpired tok of
True -> putStrLn "The token has expired!"
False -> putStrLn $ showToken tok
ありがとう!