I have recently started playing around with liquid haskell, and from all of the tutorials I could find, I could not find any examples like the following.
data MaybePerson = MaybePerson {
name' :: Maybe String,
age' :: Maybe Int
}
data Person = Person {
name :: String,
age :: Int
}
{-@ measure p :: MaybePerson -> Bool @-}
p (MaybePerson (Just _) (Just _)) = True
p _ = False
{-@ type JustPerson = {x:MaybePerson | p x} @-}
-- Attempts to instantiate a maybe person into a concrete Person
{-@ getPerson :: JustPerson -> Person @-}
getPerson (MaybePerson (Just name) (Just age)) = Person name age
getPerson _ = undefined
If I try the following, my module does not type-check, as expected:
test = getPerson (MaybePerson Nothing Nothing)
However, for some reason, the following still does not type check:
test2 = getPerson (MaybePerson (Just "bob") (Just 25))
and I get the error
Error: Liquid Type Mismatch
36 | test2 = getPerson (MaybePerson (Just "bob") (Just 25))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Inferred type
VV : {v : MaybePerson | v == ?a}
not a subtype of Required type
VV : {VV : MaybePerson | Blank.p VV}
In Context
?a : MaybePerson
Moreover, if I leave out the getPerson _ = undefined
line, I get
Your function is not total: not all patterns are defined.
Even though clearly this function is total because of the precondition specified with liquidhaskell.
What am I doing wrong here? I essentially just want to be able to reason with subtypes of a Maybe a
type which are coming from the Just
constructor, but I couldn't find any examples anywhere of where to do this properly.