Skip to content
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

Merge example (05-datatypes) won't compile #92

Open
DestyNova opened this issue Apr 18, 2020 · 9 comments
Open

Merge example (05-datatypes) won't compile #92

DestyNova opened this issue Apr 18, 2020 · 9 comments

Comments

@DestyNova
Copy link

DestyNova commented Apr 18, 2020

This may be related to issue #76, but the (temporary?) workaround listed there didn't help.

Compiling the merge example on the website produces a different error message about totality, although maybe it is relevant too. I tried invoking Liquid with the following code:

{-@ data IncList a = Emp
                | (:<) { hd :: a, tl :: IncList {v:a | hd <= v}}  @-}
data IncList a =
    Emp
  | (:<) { hd :: a, tl :: IncList a }
  deriving (Show, Eq)

infixr 9 :<

{-@ merge             :: (Ord a) => IncList a -> IncList a -> IncList a @-}
merge :: (Ord a) => IncList a -> IncList a -> IncList a
merge xs  Emp = xs
merge Emp ys  = ys
merge a@(x :< xs) b@(y :< ys)
  | x <= y    = x :< merge xs b
  | otherwise = y :< merge a ys
merge _ _ = Emp

I got this output:

$ liquid --no-termination --no-totality lh-ch5-2.hs

LiquidHaskell Version 0.8.6.0, Git revision 6f29ece8f61483f0546d052308882c8abef6da78 (dirty) [develop@6f29ece8f61483f0546d052308882c8abef6da78 (Fri Apr 17 19:03:44 2020 +0200)] 
Copyright 2013-19 Regents of the University of California. All Rights Reserved.

Targets: lh-ch5-2.hs

**** DONE:  A-Normalization ****************************************************
**** DONE:  Extracted Core using GHC *******************************************
**** DONE:  Transformed Core ***************************************************
**** DONE:  annotate ***********************************************************

**** RESULT: UNSAFE ************************************************************
 /home/omf/code/haskell/liquid/ex/lh-ch5-2.hs:15:22-31: Error: Liquid Type Mismatch
  
 15 |   | x <= y    = x :< merge xs b
                           ^^^^^^^^^^
  
   Inferred type
     VV : a
  
   not a subtype of Required type
     VV : {VV : a | x <= VV}
  
   In Context
     x : a


 /home/omf/code/haskell/liquid/ex/lh-ch5-2.hs:16:22-31: Error: Liquid Type Mismatch
  
 16 |   | otherwise = y :< merge a ys
                           ^^^^^^^^^^
  
   Inferred type
     VV : a
  
   not a subtype of Required type
     VV : {VV : a | y <= VV}
  
   In Context
     y : a

Shouldn't it infer in these cases that if x <= y, then merge xs (y :< ys) must contain only elements greater or equal to x? Apologies if this is an obvious understanding fail on my part.

@ranjitjhala
Copy link
Member

ranjitjhala commented Apr 18, 2020 via email

@DestyNova
Copy link
Author

Yes that makes sense @ranjitjhala. I was sure I tried that way first, but maybe ran into a different error and then added in the a@ and b@ references to simplify... then after eliminating the original problem, forgot to test without those references.

How embarrassing 😀

It does still seem to require either the --no-totality flag to be passed to Liquid, or the catch-all line shown in issue #76:

merge _ _ = Emp

I'm not sure why this should be needed, but it's not in the published version of the tutorial site even though it was merged in a while back. Could the site need to be rebuilt / published?

@ranjitjhala
Copy link
Member

ranjitjhala commented Apr 18, 2020 via email

@DestyNova
Copy link
Author

Thanks for the analysis @ranjitjhala! I'll open an issue and dump most of your comment into it since the case elimination internals are beyond my current comprehension 😉

@DestyNova
Copy link
Author

Alright, issue added in the main repo. Could you share the exercise answers repo with me BTW @ranjitjhala? I'm running into issues with almost every exercise and don't want to spam the issue tracker if it's just simple confusion on my part... I'm stuck right now on the del problem in chapter 5 and can't see how it could possibly done by calling delMin (i.e. what if del is called with the value of the root node? calling delMin would just walk down the tree and do something we don't want) 🤔

@ranjitjhala
Copy link
Member

No worries, just gave you access. However, please do ping me if you get too stuck, because that's VERY likely something I haven't explained properly and needs fixing!

@ranjitjhala
Copy link
Member

btw, looks like that solution for delMin is here:

https://github.com/ucsd-progsys/liquidhaskell-tutorial-solutions/blob/master/book/03-datatypes.lhs

@ranjitjhala
Copy link
Member

btw as a hint: when you remove a node (even it its the "root") you need to replace it with something else. delMin is useful to find that "replacement" ...

@DestyNova
Copy link
Author

Thanks @ranjitjhala! I peeked at the del solution and facepalmed straight away. I had the following comment in my notes... should have followed the train of thought a few steps further 😁

-- del k' t@(Node k l r) = case compare k' k of
--                           LT -> Node k (del k' l) r
--                           GT -> Node k l (del k' r)
--                           _ -> ... wait what? if we delete a middle node, we need to rewrite the tree by hoisting one of the children up :-/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants