Liquid Haskell, Haskell, . . .
.
module User where
data User = User { uRank :: Int
, uProgress :: Int
}
. Liquid Haskell {-@ blah @-}
. -1, 1, 3
RestrictedInt
:
{-@ type RestrictedInt = {v : Int | v == -1 || v == 1 || v == 3} @-}
, RestrictedInt
Int
, -1
, 1
, 3
. , , .
, int:
{-@ data User = User { uRank :: RestrictedInt
, uProgress :: Int }
@-}
This is similar to your definition, but with a restriction type instead Int
. We could include a constraint instead of having a type alias, but then your data type User
would be pretty unreadable.
You can determine good values and the tool liquid
will not complain:
goodValue :: User
goodValue = User 1 12
But bad values lead to an error:
badValue :: User
badValue = User 10 12
$ liquid so.hs
(or your integration with the editor, if you have this setting):
**** RESULT: UNSAFE ************************************************************
so.hs:16:12-18: Error: Liquid Type Mismatch
16 | badValue = User 10 12
^^^^^^^
Inferred type
VV : {VV : GHC.Types.Int | VV == ?a}
not a subtype of Required type
VV : {VV : GHC.Types.Int | VV == (-1)
|| (VV == 1
|| VV == 3)}
In Context
?a := {?a : GHC.Types.Int | ?a == (10 : int)}