-
Notifications
You must be signed in to change notification settings - Fork 139
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
Strange behavior with monadic bind #1697
Comments
@nilehmann -- this almost surely has to do with some strange interaction of (Basically means you cannot overload {-# LANGUAGE RebindableSyntax #-}
module D where
import Prelude hiding ((>>=), return)
data User = U
{-@ measure currentUser :: User @-}
{-@ data TaggedT user m a <label :: user -> Bool, clear :: user -> Bool> = TaggedT _ @-}
data TaggedT user m a = TaggedT { unTag :: m a }
{-@ data variance TaggedT invariant invariant covariant contravariant covariant @-}
{-@ assume >>= :: forall < p :: user -> Bool
, q :: user -> Bool
, r :: user -> Bool
, s :: user -> Bool
, t :: user -> Bool
, u :: user -> Bool
, rx :: a -> Bool
, rf :: a -> b -> Bool
, ro :: b -> Bool
>.
{content :: a<rx> |- b<rf content> <: b<ro>}
{content :: a<rx> |- b<ro> <: b<rf content>}
{{v : (user<s>) | True} <: {v : (user<p>) | True}}
{{v : (user<t>) | True} <: {v : (user<p>) | True}}
{{v : (user<t>) | True} <: {v : (user<r>) | True}}
{{v : (user<q>) | True} <: {v : (user<u>) | True}}
{{v : (user<s>) | True} <: {v : (user<u>) | True}}
x:TaggedT<p, q> user m (a<rx>)
-> (y:a -> TaggedT<r, s> user m (b<rf y>))
-> TaggedT<t, u> user m (b<ro>)
@-}
(>>=) :: Monad m => TaggedT user m a -> (a -> TaggedT user m b) -> TaggedT user m b
(>>=) x f = undefined -- TaggedT $ unTag x >>= \y -> unTag (f y)
{-@ assume return :: a -> TaggedT<{\_ -> True}, {\_ -> False}> user m a @-}
return :: Monad m => a -> TaggedT user m a
return x = undefined -- TaggedT (return x)
-------------------------------------------------------------------------------------------
-- | Test
-------------------------------------------------------------------------------------------
{-@ assume respondT :: String -> TaggedT<{\_ -> True}, {\v -> v == currentUser}> User m () @-}
respondT :: String -> TaggedT User m ()
respondT = undefined
{-@ test :: TaggedT<{\_ -> True}, {\v -> v == currentUser}> User m () @-}
test :: Monad m => TaggedT User m ()
test = do
z <- return "a"
respondT z |
@ranjitjhala, thanks for the suggestion. I think it will be enough to have a proof of concept of the library-ification. So, I should be good for now. |
The solution to make should get
In other words, all the refinements are lost on the constraints |
I don't quite understand the solution, but why is there a difference between refining Also, is this related to instantiating |
@nilehmann i don’t follow your mapM remark, aren’t you missing some m in the signature? |
@ranjitjhala, yeah I missed some
but we'd like it to be more like
|
Can you add this as a concrete code snippet to this issue? Eg we want X.hs
to be safe (if mapM is instantiated correctly?) as I understand it Niki’s
suggestion may/should Address this too so I can see if the edit she
suggests helps
…On Thu, Jul 23, 2020 at 11:17 AM Nico Lehmann ***@***.***> wrote:
@ranjitjhala
<https://urldefense.com/v3/__https://github.com/ranjitjhala__;!!Mih3wA!ViXO-Q2HZINM-UPZL2TY6EwMPsOKsYATyuleK0cYy10zmmxtmz73Kd5UGT9zNmCZ$>,
yeah I missed some m's. Right now I think mapM is instantiated with:
mapM :: (a -> TaggedT<{\_ -> True}, {\_ -> True}> m b) -> t a -> TaggedT<{\_ -> True}, {\_ -> True}> m (t b)
but we'd like it to be more like
mapM :: (a -> TaggedT<p, q> m b) -> t a -> TaggedT<p, q> m (t b)
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<https://urldefense.com/v3/__https://github.com/ucsd-progsys/liquidhaskell/issues/1697*issuecomment-663157865__;Iw!!Mih3wA!ViXO-Q2HZINM-UPZL2TY6EwMPsOKsYATyuleK0cYy10zmmxtmz73Kd5UGS2Pw9Ou$>,
or unsubscribe
<https://urldefense.com/v3/__https://github.com/notifications/unsubscribe-auth/AAMS4OA5M535ACR7DNPIINDR5B5CVANCNFSM4OPOM72A__;!!Mih3wA!ViXO-Q2HZINM-UPZL2TY6EwMPsOKsYATyuleK0cYy10zmmxtmz73Kd5UGQ1qGi9F$>
.
|
Thinking some more the isGeneric should be necessary to get the mapM
working properly but may not be sufficient...
…On Thu, Jul 23, 2020 at 11:20 AM Ranjit Jhala ***@***.***> wrote:
Can you add this as a concrete code snippet to this issue? Eg we want X.hs
to be safe (if mapM is instantiated correctly?) as I understand it Niki’s
suggestion may/should Address this too so I can see if the edit she
suggests helps
On Thu, Jul 23, 2020 at 11:17 AM Nico Lehmann ***@***.***>
wrote:
> @ranjitjhala
> <https://urldefense.com/v3/__https://github.com/ranjitjhala__;!!Mih3wA!ViXO-Q2HZINM-UPZL2TY6EwMPsOKsYATyuleK0cYy10zmmxtmz73Kd5UGT9zNmCZ$>,
> yeah I missed some m's. Right now I think mapM is instantiated with:
>
> mapM :: (a -> TaggedT<{\_ -> True}, {\_ -> True}> m b) -> t a -> TaggedT<{\_ -> True}, {\_ -> True}> m (t b)
>
> but we'd like it to be more like
>
> mapM :: (a -> TaggedT<p, q> m b) -> t a -> TaggedT<p, q> m (t b)
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub
> <https://urldefense.com/v3/__https://github.com/ucsd-progsys/liquidhaskell/issues/1697*issuecomment-663157865__;Iw!!Mih3wA!ViXO-Q2HZINM-UPZL2TY6EwMPsOKsYATyuleK0cYy10zmmxtmz73Kd5UGS2Pw9Ou$>,
> or unsubscribe
> <https://urldefense.com/v3/__https://github.com/notifications/unsubscribe-auth/AAMS4OA5M535ACR7DNPIINDR5B5CVANCNFSM4OPOM72A__;!!Mih3wA!ViXO-Q2HZINM-UPZL2TY6EwMPsOKsYATyuleK0cYy10zmmxtmz73Kd5UGQ1qGi9F$>
> .
>
|
@nikivazou your solution doesn't work. When I make module Foo () where
import Language.Haskell.Liquid.Prelude
gpp :: Monad m => m Int -> m Int
gpp z = do x <- z
return $ liquidAssert (x > 0) (x - 10)
{-@ xs :: Maybe {v:Int | v > 0} @-}
xs :: Maybe Int
xs = Just 9
ys :: Maybe Int
ys = gpp xs The reason this gets verified is that LH synthesizes the type gpp :: (Monad m) => m Pos -> {v:m | false} Int and hence that ys :: {v: Maybe Int | false} after which it is all game over... Now, I don't know why making The code is something like: gpp z = z >>= \x -> return (...) Now, I can see that the return :: a -> m a so but I'm puzzled by the >>= :: m a -> (a -> m b) -> m b so if we have an instance: {m | km} ka -> (ka -> {m | k} kb) -> {m| k} kb where then, as the type of
due to the two arguments to
UNLESS in the constraint splitting for Higher Kinded types like this splitC (SubC γ t1@(RAppTy r1 r1' _) t2@(RAppTy r2 r2' _))
= do cs <- bsplitC γ t1 t2
cs' <- splitC (SubC γ r1 r2)
cs'' <- splitC (SubC γ r1' r2')
cs''' <- splitC (SubC γ r2' r1')
return $ cs ++ cs' ++ cs'' ++ cs''' I am confused why is there BOTH Anyway -- long story short, just marking |
Btw, @nikivazou here's a stripped down version that is unsoundly marked "safe" with "generic" module Foo () where
gpp :: Monad m => m Int -> m Int
gpp z = do
x <- z
return x
{-@ ys :: {v: Maybe Int | false } @-}
ys :: Maybe Int
ys = gpp (Just 0) |
Further simplification yields this: module Foo () where
rebindMonad :: Monad m => m Int -> m Int
rebindMonad z = do
x <- z
return x
{-@ rebindMaybe :: {v:_ | true} -> {v:_| false} @-}
rebindMaybe :: Maybe Int -> Maybe Int
rebindMaybe = rebindMonad I think the problem is this: LH infers rebindMonad :: Monad m => m Int -> {v:m | false} Int but then when we do the actual specialization to the
So maybe it has to do with how we're dealing with application/substitution of HKT? Also, its odd that we should attach a refinement with the |
@ranjitjhala it seems that all the "unsound" examples you have are soundly unsafe with the Here is exactly why we need a fresh
with
Currently, the only way to unify bind's result |
Via @nilehmann
https://gist.github.com/nilehmann/8ace3dd793dc78bf0af04f8ee3585b84
A.hs
the code is safe using a monad whereUser
is hardwiredB.hs
the code is unsafe using a monad whereuser
is a parameterC.hs
the code is safe where we use a plainbindT
andreturnT
Some mysterious goings on.
A.hs
,B.hs
demanding that--no-pattern-inline
? Both use refined monads?A
is safe with 1 checked constraint whileC
has 28 checked constraints?C.hs
need theassume
statements butA
andB
do not? (are instance signatures "assumed" by default??)@nikivazou -- I think you will need definitely need to take a look at this, it touches two things that I'm unfamiliar
with (the instances and bounds) but I'm guessing that won't happen until the after your deadline next week?
The text was updated successfully, but these errors were encountered: