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

Issues with quickSort in chapter 6 #79

Open
skyzh opened this issue Feb 16, 2019 · 7 comments
Open

Issues with quickSort in chapter 6 #79

skyzh opened this issue Feb 16, 2019 · 7 comments

Comments

@skyzh
Copy link
Contributor

skyzh commented Feb 16, 2019

Hello! I encountered some problems when I was trying solving exercise 6.6

Exercise 6.6 (QuickSort). Use partition to implement quickSort.
-- >> quickSort [1,4,3,2] 
-- [1,2,3,4] 
{-@ quickSort :: (Ord a) => xs:List a -> ListX a xs @-} 
quickSort [] = [] 
quickSort (x:xs) = undefined 
{-@ test10 :: ListN String 2 @-} 
test10 = quickSort test4

Here's my implementation:

{-@ partition :: _ -> xs:_ -> {v:_ | Sum2 v (size xs)} @-}
{-@ predicate Sum2 X N = size (fst X) + size (snd X) = N @-}

partition :: (a -> Bool) -> [a] -> ([a], [a])
partition _ [] = ([], [])
partition f (x:xs)
  | f x = (x:ys, zs)
  | otherwise = (ys, x:zs)
  where
    (ys, zs) = partition f xs

-- exercise 6.6
{-@ quickSort' :: (Ord a) => xs:List a -> ListX a xs @-}
quickSort' :: (Ord a) => [a] -> [a]
quickSort' [] = []
quickSort' (x:xs) = let
  (l, r) = partition cmp xs
  cmp t = t < x in
     quickSort' l ++ [x] ++ quickSort' r

Which I got the following error:

 /Users/skyzh/Work/playground/src/Ex06.hs:152:6-17: Error: Liquid Type Mismatch

 152 |      quickSort' l ++ [x] ++ quickSort' r
            ^^^^^^^^^^^^

   Inferred type
     VV : {v : [a##xo] | len v >= 0
                         && v == fst ?a
                         && v /= ?b
                         && Ex06.size v >= 0}

   not a subtype of Required type
     VV : {VV : [a##xo] | len VV < len ?b
                          && len VV >= 0}

   In Context
     xs : {v : [a##xo] | Ex06.size v >= 0
                         && len v >= 0}

     ?b : {?b : [a##xo] | Ex06.size ?b >= 0
                          && len ?b >= 0}

     x : a##xo

     ?a : {?a : ([a##xo], [a##xo]) | Ex06.size (fst ?a) + Ex06.size (snd ?a) == Ex06.size xs}


 /Users/skyzh/Work/playground/src/Ex06.hs:152:6-40: Error: Liquid Type Mismatch

 152 |      quickSort' l ++ [x] ++ quickSort' r
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

   Inferred type
     VV : {v : [a##xo] | len v == len ?f + len ?b
                         && Ex06.size v >= 0
                         && len v >= 0}

   not a subtype of Required type
     VV : {VV : [a##xo] | Ex06.size VV == Ex06.size ?e}

   In Context
     ?g : {?g : [a##xo] | (Ex06.notEmpty ?g <=> false)
                          && Ex06.size ?g == 0
                          && len ?g == 0
                          && Ex06.size ?g >= 0
                          && len ?g >= 0}

     xs : {v : [a##xo] | Ex06.size v >= 0
                         && len v >= 0}

     ?f : {?f : [a##xo] | Ex06.size ?f == Ex06.size (fst ?c)
                          && Ex06.size ?f >= 0
                          && len ?f >= 0}

     ?c : {?c : ([a##xo], [a##xo]) | Ex06.size (fst ?c) + Ex06.size (snd ?c) == Ex06.size xs}

     ?e : {?e : [a##xo] | Ex06.size ?e >= 0
                          && len ?e >= 0}

     ?b : {?b : [a##xo] | len ?b == len ?a + len ?d
                          && Ex06.size ?b >= 0
                          && len ?b >= 0}

     x : a##xo

     ?d : {?d : [a##xo] | Ex06.size ?d == Ex06.size (snd ?c)
                          && Ex06.size ?d >= 0
                          && len ?d >= 0}

     ?a : {?a : [a##xo] | tail ?a == ?g
                          && head ?a == x
                          && (Ex06.notEmpty ?a <=> true)
                          && Ex06.size ?a == 1 + Ex06.size ?g
                          && len ?a == 1 + len ?g
                          && Ex06.size ?a >= 0
                          && len ?a >= 0}


 /Users/skyzh/Work/playground/src/Ex06.hs:152:29-40: Error: Liquid Type Mismatch

 152 |      quickSort' l ++ [x] ++ quickSort' r
                                   ^^^^^^^^^^^^

   Inferred type
     VV : {v : [a##xo] | len v >= 0
                         && v == snd ?a
                         && v /= ?b
                         && Ex06.size v >= 0}

   not a subtype of Required type
     VV : {VV : [a##xo] | len VV < len ?b
                          && len VV >= 0}

   In Context
     xs : {v : [a##xo] | Ex06.size v >= 0
                         && len v >= 0}

     ?b : {?b : [a##xo] | Ex06.size ?b >= 0
                          && len ?b >= 0}

     x : a##xo

     ?a : {?a : ([a##xo], [a##xo]) | Ex06.size (fst ?a) + Ex06.size (snd ?a) == Ex06.size xs}

And I suspect that Liquid Haskell may fail to deduce the size of operator ++. Then I made an experiment to test.

{-@ (+++) :: xs: List a -> ys: List a -> ListN a {size xs + size ys} @-}
(+++) :: [a] -> [a] -> [a]
a +++ b = a ++ b

And certainly I got the following error:

/Users/skyzh/Work/playground/src/Ex06.hs:143:11-16: Error: Liquid Type Mismatch

 143 | a +++ b = a ++ b
                 ^^^^^^

   Inferred type
     VV : {v : [a##xo] | len v == len a + len b
                         && Ex06.size v >= 0
                         && len v >= 0}

   not a subtype of Required type
     VV : {VV : [a##xo] | Ex06.size VV == Ex06.size a + Ex06.size b}

   In Context
     a : {a : [a##xo] | Ex06.size a >= 0
                        && len a >= 0}

     b : {b : [a##xo] | Ex06.size b >= 0
                        && len b >= 0}

Is there anyway to make Liquid Haskell deduce that ++ can correctly add up size?

Thank you for reading this issue!

@skyzh skyzh changed the title issues with quickSort in chapter 7 Issues with quickSort in chapter 7 Feb 16, 2019
@skyzh skyzh changed the title Issues with quickSort in chapter 7 Issues with quickSort in chapter 6 Feb 16, 2019
@skyzh
Copy link
Contributor Author

skyzh commented Feb 16, 2019

I've also tested my code on the online version, which caused the same issue. http://ucsd-progsys.github.io/liquidhaskell-tutorial/07-measure-int.html#/program-40

image

@ranjitjhala
Copy link
Member

ranjitjhala commented Feb 16, 2019 via email

@ranjitjhala
Copy link
Member

ranjitjhala commented Feb 16, 2019 via email

@skyzh
Copy link
Contributor Author

skyzh commented Feb 16, 2019

Thank you for your response! I've just figured out a working example by defining pivApp similar to http://goto.ucsd.edu/~gridaphobe/liquid/haskell/blog/blog/2013/07/29/putting-things-in-order.lhs/

https://github.com/SkyZH/introliquid.hs/blob/master/src/Ex06.hs#L150

@ranjitjhala
Copy link
Member

ranjitjhala commented Feb 16, 2019 via email

@skyzh
Copy link
Contributor Author

skyzh commented Feb 16, 2019

I've missed your first reply...

  1. use “Len” instead of “size” In the spec of “partition” does not help, because ListN is defined by size...

  2. tell LH that “Len” is the same as “size” by specifying that does not help.

{-@ measure size @-}
{-@ size :: xs:[a] -> {v:Nat | v = len xs} @-}
size :: [a] -> Int
size [] = 0
size (_:rs) = 1 + size rs
/Users/skyzh/Work/playground/src/Ex06.hs:157:5-17: Error: Liquid Type Mismatch

 157 |     l ++ [x] ++ r
           ^^^^^^^^^^^^^

   Inferred type
     VV : {v : [a##xo] | len v == len (Ex06.fst ?f) + len ?b
                         && Ex06.size v >= 0
                         && len v >= 0}

   not a subtype of Required type
     VV : {VV : [a##xo] | Ex06.size VV == Ex06.size ?e}

   In Context
     xs : {v : [a##xo] | Ex06.size v >= 0
                         && len v >= 0}

     ?f : {?f : ([a##xo], [a##xo]) | Ex06.size (fst ?f) + Ex06.size (snd ?f) == Ex06.size xs
                                     && len (fst ?f) + len (snd ?f) == Ex06.size xs}

     ?c : {?c : [a##xo] | tail ?c == ?a
                          && head ?c == x
                          && (Ex06.notEmpty ?c <=> true)
                          && Ex06.size ?c == 1 + Ex06.size ?a
                          && len ?c == 1 + len ?a
                          && Ex06.size ?c >= 0
                          && len ?c >= 0}

     ?e : {?e : [a##xo] | Ex06.size ?e >= 0
                          && len ?e >= 0}

     ?b : {?b : [a##xo] | len ?b == len ?c + len (Ex06.snd ?f)
                          && Ex06.size ?b >= 0
                          && len ?b >= 0}

     x : a##xo

     ?a : {?a : [a##xo] | (Ex06.notEmpty ?a <=> false)
                          && Ex06.size ?a == 0
                          && len ?a == 0
                          && Ex06.size ?a >= 0
                          && len ?a >= 0}
  1. replace all size with len this is ok 💯, here's the working example https://github.com/SkyZH/introliquid.hs/blob/master/src/Ex06len.hs

@skyzh
Copy link
Contributor Author

skyzh commented Feb 16, 2019

  1. tell LH that “Len” is the same as “size” by specifying that still does not help if I change the definition from the one in the previous comment into:
  {-@ measure size @-}
- {-@ size :: xs::[a]-> {v:Nat | v = len xs} @-}
+ {-@ size :: xs:_ -> {v:Nat | v = len xs} @-}
  size :: [a] -> Int
  size [] = 0
  size (_:rs) = 1 + size rs

which yields exactly the same error.

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