Closed NorfairKing closed 7 years ago
Hi @NorfairKing,
Thanks for this example (& sorry for the delay!)
Unfortunately, dropWhile
is rather more complicated,
and you can't do it "directly" in this style due to various
current implementation limitations.
es
thing is (I believe) solved in develop
...
earlier you couldn't have refinements in measures...not (Prop (p (head o)))
is
currently not supported, primarily as you cannot
directly use the higher order predicate p
inside
the specifications. (In general, you can only use
measures + arithmetic in specifications).So, instead you need to define "lists whose head satisfies some property p" which we can do like so:
{-@ data List a <p :: a -> Prop> = Emp
| (:::) { hd :: a<p>
, tl :: List a }
@-}
After which, dropWhile
looks like
{-@ dropWhile :: forall <p :: a -> Prop, w :: a -> Bool -> Prop>.
(Witness a p w) =>
(x:a -> Bool<w x>) -> List a -> List <p> a
@-}
dropWhile :: (a -> Bool) -> List a -> List a
dropWhile f (x:::xs)
| not (f x) = x ::: xs
| otherwise = dropWhile f xs
dropWhile f Emp = Emp
{-@ bound witness @-}
witness :: Eq a => (a -> Bool) -> (a -> Bool -> Bool) -> a -> Bool -> a -> Bool
witness p w = \ y b v -> (not b) ==> w y b ==> (v == y) ==> p v
The strange Witness
thing says that
f x
returns a Bool
that is False
x
satisfies the predicate p
We then have that the output of dropWhile
has a head that satisfies p
,
after which the rest follows.
In short: this is rather clunky It would be much nicer to support a spec like yours; and perhaps we can figure out how to get there...
Thank you for the response!
The type of dropWhile could be more specific:
This way we can prove the following safe:
Unfortunately there are two problems:
es
is unbound in the new liquid signature forhead
.==
only works forEq
types, so I'm not sure how to specifye == head es
.Feedback/help is welcome.