-
Notifications
You must be signed in to change notification settings - Fork 135
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
GADT without refinement throws "specified type does not refine Haskell type" error #2287
Comments
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. |
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 |
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 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. |
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
The text was updated successfully, but these errors were encountered: