Open jvanbruegge opened 4 months ago
I also tried add a refinement type signature and replace pretty much everything with underscores but that did not help either
I think LH simply does not “know” about these newer GHC features. That said, can you post your mergeTree code? Ideally all the Nat stuff should just be in refinements so I wonder if we can make a simpler version work…
Here is the whole file: Heap.hs
Thanks! The below seems to work fine:
{-# OPTIONS_GHC -fplugin=LiquidHaskell #-}
{-# LANGUAGE GADTs #-}
{-@ LIQUID "--reflection" @-}
{-@ LIQUID "--ple" @-}
module Heap where
import Language.Haskell.Liquid.Equational
-------------------------------------------------------------------------------
data Binary
= B0 Binary
| B1 Binary
| BEnd
data DecList t a where
DNil :: DecList t a
DCons :: t a -> DecList t a -> DecList t a
data Tree a where
MkTree :: a -> DecList Tree a -> Tree a
data Forest a where
FEnd :: Forest a
F0 :: Forest a -> Forest a
F1 :: Tree a -> Forest a -> Forest a
{-@ measure pot @-}
{-@ pot :: Forest a -> Nat @-}
pot :: Forest a -> Int
pot FEnd = 0
pot (F0 rest) = pot rest
pot (F1 _ rest) = 1 + pot rest
{-@ reflect mergeTree @-}
mergeTree :: Ord a => Tree a -> Tree a -> Tree a
mergeTree l@(MkTree lr lc) r@(MkTree rr rc)
| lr <= rr = MkTree lr (DCons r lc)
| otherwise = MkTree rr (DCons l rc)
{-@ reflect insertTree @-}
insertTree :: Ord a => Tree a -> Forest a -> Forest a
insertTree t FEnd = F1 t FEnd
insertTree t (F0 f) = F1 t f
insertTree t (F1 t' f) = F0 (insertTree (mergeTree t t') f)
{-@ reflect insertTreeT @-}
insertTreeT :: Ord a => Tree a -> Forest a -> Int
insertTreeT _ FEnd = 1
insertTreeT _ (F0 _) = 1
insertTreeT t (F1 t' f) = 1 + insertTreeT (mergeTree t t') f
{-@ insertTreeAmortized :: t:_ -> f:_ -> { insertTreeT t f + pot (insertTree t f) - pot f <= 2 } @-}
insertTreeAmortized :: Ord a => Tree a -> Forest a -> Proof
insertTreeAmortized t FEnd = ()
insertTreeAmortized t (F0 rest) = ()
insertTreeAmortized t (F1 t' rest) = insertTreeAmortized (mergeTree t t') rest
Yeah, not using GADTs works, but I was hoping to use fancy types to ensure correctness. Is DataKinds just not supported by LH?
I don't think so, sadly. Maybe @facundominguez and @nikivazou know more? [ I think there was some very limited support but perhaps its rather brittle? ]
I think "in theory" it shouldn't be hard, because LH doesn't really need to know much about them -- just follow GHC -- but I think "in practice" we just haven't updated the connection ... ?
Hmm this is a very interesting use of the DataKinds
-- thanks for pointing it out!
LH doesn't really need to know much about them
This would be my expectation, but I haven't worked with this part of the code base yet.
Well, from the error message, it seems that the refined type for the "worker" data constructor Heap.$WF1
is not well produced.
GHC generates two types of data constructors, the worker and the the wrapper. In Liquid Haskell we generate the type of the worker based on the user provided type. I suspect that these newer GHC features generate more fancy worker types. So, even though LH does not need to know much about these features, we need to at least, update the generation of the worker type.
The following code
throws an error for the
Forest
type:However, the definition is accepted if converted to existential style:
but sadly this fails when trying to prove anything using
reflect
:with the error