Is `x >> pure y` equivalent to `liftM (const y) x`Unlike a Functor, a Monad can change shape?Why should Applicative be a superclass of Monad?Is there a monad that doesn't have a corresponding monad transformer (except IO)?Composition of compositions in HaskellHaskell: Flaw in the description of applicative functor laws in the hackage Control.Applicative article?: it says Applicative determines FunctorTo what extent are Applicative/Monad instances uniquely determined?Is this property of a functor stronger than a monad?Are applicative functors composed with the applicative style really independent?bind can be composed of fmap and join, so do we have to use monadic functions a -> m b?Do the monadic liftM and the functorial fmap have to be equivalent?
Is `x >> pure y` equivalent to `liftM (const y) x`
Fastening aluminum fascia to wooden subfascia
Is expanding the research of a group into machine learning as a PhD student risky?
What does "I’d sit this one out, Cap," imply or mean in the context?
Purchasing a ticket for someone else in another country?
Lay out the Carpet
How does it work when somebody invests in my business?
How to be diplomatic in refusing to write code that breaches the privacy of our users
Failed to fetch jessie backports repository
What is paid subscription needed for in Mortal Kombat 11?
System.debug(JSON.Serialize(o)) Not longer shows full string
Is there a problem with hiding "forgot password" until it's needed?
How does the UK government determine the size of a mandate?
What is the best translation for "slot" in the context of multiplayer video games?
Why Were Madagascar and New Zealand Discovered So Late?
What is the intuitive meaning of having a linear relationship between the logs of two variables?
Why not increase contact surface when reentering the atmosphere?
How to Reset Passwords on Multiple Websites Easily?
Is a stroke of luck acceptable after a series of unfavorable events?
Closest Prime Number
Hostile work environment after whistle-blowing on coworker and our boss. What do I do?
Why escape if the_content isnt?
How do scammers retract money, while you can’t?
Balance Issues for a Custom Sorcerer Variant
Is `x >> pure y` equivalent to `liftM (const y) x`
Unlike a Functor, a Monad can change shape?Why should Applicative be a superclass of Monad?Is there a monad that doesn't have a corresponding monad transformer (except IO)?Composition of compositions in HaskellHaskell: Flaw in the description of applicative functor laws in the hackage Control.Applicative article?: it says Applicative determines FunctorTo what extent are Applicative/Monad instances uniquely determined?Is this property of a functor stronger than a monad?Are applicative functors composed with the applicative style really independent?bind can be composed of fmap and join, so do we have to use monadic functions a -> m b?Do the monadic liftM and the functorial fmap have to be equivalent?
The two expressions
y >> pure x
liftM (const x) y
have the same type signature in Haskell.
I was curious whether they were equivalent, but I could neither produce a proof of the fact nor a counter example against it.
If we rewrite the two expressions so that we can eliminate the x and y then the question becomes whether the two following functions are equivalent
flip (>>) . pure
liftM . const
Note that both these functions have type Monad m => a -> m b -> m a.
I used the laws that Haskell gives for monad, applicatives, and functors to transform both statements into various equivalent forms, but I was not able to produce a sequence of equivalences between the two.
For instance I found that y >> pure x can be rewritten as follows
y >>= const (pure x)
y *> pure x
(id <$ y) <*> pure x
fmap (const id) y <*> pure x
and liftM (const x) y can be rewritten as follows
fmap (const x) y
pure (const x) <*> y
None of these spring out to me as necessarily equivalent, but I cannot think of any cases where they would not be equivalent.
haskell monads functor applicative
add a comment |
The two expressions
y >> pure x
liftM (const x) y
have the same type signature in Haskell.
I was curious whether they were equivalent, but I could neither produce a proof of the fact nor a counter example against it.
If we rewrite the two expressions so that we can eliminate the x and y then the question becomes whether the two following functions are equivalent
flip (>>) . pure
liftM . const
Note that both these functions have type Monad m => a -> m b -> m a.
I used the laws that Haskell gives for monad, applicatives, and functors to transform both statements into various equivalent forms, but I was not able to produce a sequence of equivalences between the two.
For instance I found that y >> pure x can be rewritten as follows
y >>= const (pure x)
y *> pure x
(id <$ y) <*> pure x
fmap (const id) y <*> pure x
and liftM (const x) y can be rewritten as follows
fmap (const x) y
pure (const x) <*> y
None of these spring out to me as necessarily equivalent, but I cannot think of any cases where they would not be equivalent.
haskell monads functor applicative
add a comment |
The two expressions
y >> pure x
liftM (const x) y
have the same type signature in Haskell.
I was curious whether they were equivalent, but I could neither produce a proof of the fact nor a counter example against it.
If we rewrite the two expressions so that we can eliminate the x and y then the question becomes whether the two following functions are equivalent
flip (>>) . pure
liftM . const
Note that both these functions have type Monad m => a -> m b -> m a.
I used the laws that Haskell gives for monad, applicatives, and functors to transform both statements into various equivalent forms, but I was not able to produce a sequence of equivalences between the two.
For instance I found that y >> pure x can be rewritten as follows
y >>= const (pure x)
y *> pure x
(id <$ y) <*> pure x
fmap (const id) y <*> pure x
and liftM (const x) y can be rewritten as follows
fmap (const x) y
pure (const x) <*> y
None of these spring out to me as necessarily equivalent, but I cannot think of any cases where they would not be equivalent.
haskell monads functor applicative
The two expressions
y >> pure x
liftM (const x) y
have the same type signature in Haskell.
I was curious whether they were equivalent, but I could neither produce a proof of the fact nor a counter example against it.
If we rewrite the two expressions so that we can eliminate the x and y then the question becomes whether the two following functions are equivalent
flip (>>) . pure
liftM . const
Note that both these functions have type Monad m => a -> m b -> m a.
I used the laws that Haskell gives for monad, applicatives, and functors to transform both statements into various equivalent forms, but I was not able to produce a sequence of equivalences between the two.
For instance I found that y >> pure x can be rewritten as follows
y >>= const (pure x)
y *> pure x
(id <$ y) <*> pure x
fmap (const id) y <*> pure x
and liftM (const x) y can be rewritten as follows
fmap (const x) y
pure (const x) <*> y
None of these spring out to me as necessarily equivalent, but I cannot think of any cases where they would not be equivalent.
haskell monads functor applicative
haskell monads functor applicative
edited 1 hour ago
duplode
23.1k44987
23.1k44987
asked 3 hours ago
10000000001000000000
464214
464214
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
Yes they are the same
Let's start with flip (>>) . pure, which is the pointfree version of x >> pure y you provide:
flip (>>) . pure
It is the case that flip (>>) is just (=<<) . const so we can rewrite this as:
((=<<) . const) . pure
Since function composition ((.)) is associative we can write this as:
(=<<) . (const . pure)
We can rewrite const . pure as fmap pure . const:
(=<<) . (fmap pure . const)
Now we associate again:
((=<<) . fmap pure) . const
Since (=<<) has type
(=<<) :: Monad m => (a -> m b) -> m a -> m b
we know fmap pure must be a subtype of Monad m => c -> (a -> m b). If we unify this with it's type of
fmap pure :: (Applicative f1, Functor f2) => f2 a -> f2 (f1 a)
We get Monad m => (a -> b) -> (a -> m b). Meaning our functor is (a ->). Since (.) is fmap over the functor (a ->) we can replace our fmap with (.).
((=<<) . (.) pure) . const
((=<<) . (.) pure) is the definition for liftM1 so we can substitute:
liftM . const
And that is the goal. The two are the same.
1: The definition of liftM is liftM f m1 = do x1 <- m1; return (f x1) , we can desugar the do into liftM f m1 = m1 >>= return . f. We can flip the (>>=) for liftM f m1 = return . f =<< m1 and elide the m1 to get liftM f = (return . f =<<) a little pointfree magic and we get liftM = (=<<) . (.) return
add a comment |
The other answer gets there eventually, but it takes a long-winded route. All that is actually needed are the definitions of liftM, const, and a single monad law: m1 >> m2 and m1 >>= _ -> m2 must be semantically identical. (Indeed, this is the default implementation of (>>), and it is rare to override it.) Then:
liftM (const x) y
= definition of liftM*
y >>= z -> pure (const x z)
= definition of const
y >>= z -> pure x
= monad law
y >> pure x
* Okay, okay, so the actual definition of liftM uses return instead of pure. Whatever.
Interesting. For some reason I thought that the standard definition wasliftM = fmap, with the more restrictive type. With the real definition above, the wanted equation is much simpler to obtain :)
– chi
2 hours ago
1
@chi Even without it things aren't too bad:fmap f m = m >>= return . fis also a monad law (one of the oft-forgotten ones).
– Daniel Wagner
1 hour ago
1
That law itself follows from parametricity and the monad lawm >>= pure = m.
– dfeuer
38 mins ago
add a comment |
One more possible route, exploiting the applicative laws:
For instance I found that
y >> pure xcan be rewritten as follows [...]fmap (const id) y <*> pure x
That amounts to...
fmap (const id) y <*> pure x
pure ($ x) <*> fmap (const id) y -- interchange law of applicatives
($ x) <$> fmap (const id) y -- fmap in terms of <*>
fmap (($ x) . const id) y -- composition law of functors
fmap (const x) y
... which, as you noted, is the same as liftM (const x) y.
That this route requires only applicative laws and not monad ones reflects how (*>) (another name for (>>)) is an Applicative method.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55384267%2fis-x-pure-y-equivalent-to-liftm-const-y-x%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
Yes they are the same
Let's start with flip (>>) . pure, which is the pointfree version of x >> pure y you provide:
flip (>>) . pure
It is the case that flip (>>) is just (=<<) . const so we can rewrite this as:
((=<<) . const) . pure
Since function composition ((.)) is associative we can write this as:
(=<<) . (const . pure)
We can rewrite const . pure as fmap pure . const:
(=<<) . (fmap pure . const)
Now we associate again:
((=<<) . fmap pure) . const
Since (=<<) has type
(=<<) :: Monad m => (a -> m b) -> m a -> m b
we know fmap pure must be a subtype of Monad m => c -> (a -> m b). If we unify this with it's type of
fmap pure :: (Applicative f1, Functor f2) => f2 a -> f2 (f1 a)
We get Monad m => (a -> b) -> (a -> m b). Meaning our functor is (a ->). Since (.) is fmap over the functor (a ->) we can replace our fmap with (.).
((=<<) . (.) pure) . const
((=<<) . (.) pure) is the definition for liftM1 so we can substitute:
liftM . const
And that is the goal. The two are the same.
1: The definition of liftM is liftM f m1 = do x1 <- m1; return (f x1) , we can desugar the do into liftM f m1 = m1 >>= return . f. We can flip the (>>=) for liftM f m1 = return . f =<< m1 and elide the m1 to get liftM f = (return . f =<<) a little pointfree magic and we get liftM = (=<<) . (.) return
add a comment |
Yes they are the same
Let's start with flip (>>) . pure, which is the pointfree version of x >> pure y you provide:
flip (>>) . pure
It is the case that flip (>>) is just (=<<) . const so we can rewrite this as:
((=<<) . const) . pure
Since function composition ((.)) is associative we can write this as:
(=<<) . (const . pure)
We can rewrite const . pure as fmap pure . const:
(=<<) . (fmap pure . const)
Now we associate again:
((=<<) . fmap pure) . const
Since (=<<) has type
(=<<) :: Monad m => (a -> m b) -> m a -> m b
we know fmap pure must be a subtype of Monad m => c -> (a -> m b). If we unify this with it's type of
fmap pure :: (Applicative f1, Functor f2) => f2 a -> f2 (f1 a)
We get Monad m => (a -> b) -> (a -> m b). Meaning our functor is (a ->). Since (.) is fmap over the functor (a ->) we can replace our fmap with (.).
((=<<) . (.) pure) . const
((=<<) . (.) pure) is the definition for liftM1 so we can substitute:
liftM . const
And that is the goal. The two are the same.
1: The definition of liftM is liftM f m1 = do x1 <- m1; return (f x1) , we can desugar the do into liftM f m1 = m1 >>= return . f. We can flip the (>>=) for liftM f m1 = return . f =<< m1 and elide the m1 to get liftM f = (return . f =<<) a little pointfree magic and we get liftM = (=<<) . (.) return
add a comment |
Yes they are the same
Let's start with flip (>>) . pure, which is the pointfree version of x >> pure y you provide:
flip (>>) . pure
It is the case that flip (>>) is just (=<<) . const so we can rewrite this as:
((=<<) . const) . pure
Since function composition ((.)) is associative we can write this as:
(=<<) . (const . pure)
We can rewrite const . pure as fmap pure . const:
(=<<) . (fmap pure . const)
Now we associate again:
((=<<) . fmap pure) . const
Since (=<<) has type
(=<<) :: Monad m => (a -> m b) -> m a -> m b
we know fmap pure must be a subtype of Monad m => c -> (a -> m b). If we unify this with it's type of
fmap pure :: (Applicative f1, Functor f2) => f2 a -> f2 (f1 a)
We get Monad m => (a -> b) -> (a -> m b). Meaning our functor is (a ->). Since (.) is fmap over the functor (a ->) we can replace our fmap with (.).
((=<<) . (.) pure) . const
((=<<) . (.) pure) is the definition for liftM1 so we can substitute:
liftM . const
And that is the goal. The two are the same.
1: The definition of liftM is liftM f m1 = do x1 <- m1; return (f x1) , we can desugar the do into liftM f m1 = m1 >>= return . f. We can flip the (>>=) for liftM f m1 = return . f =<< m1 and elide the m1 to get liftM f = (return . f =<<) a little pointfree magic and we get liftM = (=<<) . (.) return
Yes they are the same
Let's start with flip (>>) . pure, which is the pointfree version of x >> pure y you provide:
flip (>>) . pure
It is the case that flip (>>) is just (=<<) . const so we can rewrite this as:
((=<<) . const) . pure
Since function composition ((.)) is associative we can write this as:
(=<<) . (const . pure)
We can rewrite const . pure as fmap pure . const:
(=<<) . (fmap pure . const)
Now we associate again:
((=<<) . fmap pure) . const
Since (=<<) has type
(=<<) :: Monad m => (a -> m b) -> m a -> m b
we know fmap pure must be a subtype of Monad m => c -> (a -> m b). If we unify this with it's type of
fmap pure :: (Applicative f1, Functor f2) => f2 a -> f2 (f1 a)
We get Monad m => (a -> b) -> (a -> m b). Meaning our functor is (a ->). Since (.) is fmap over the functor (a ->) we can replace our fmap with (.).
((=<<) . (.) pure) . const
((=<<) . (.) pure) is the definition for liftM1 so we can substitute:
liftM . const
And that is the goal. The two are the same.
1: The definition of liftM is liftM f m1 = do x1 <- m1; return (f x1) , we can desugar the do into liftM f m1 = m1 >>= return . f. We can flip the (>>=) for liftM f m1 = return . f =<< m1 and elide the m1 to get liftM f = (return . f =<<) a little pointfree magic and we get liftM = (=<<) . (.) return
edited 1 hour ago
answered 3 hours ago
Sriotchilism O'ZaicSriotchilism O'Zaic
808620
808620
add a comment |
add a comment |
The other answer gets there eventually, but it takes a long-winded route. All that is actually needed are the definitions of liftM, const, and a single monad law: m1 >> m2 and m1 >>= _ -> m2 must be semantically identical. (Indeed, this is the default implementation of (>>), and it is rare to override it.) Then:
liftM (const x) y
= definition of liftM*
y >>= z -> pure (const x z)
= definition of const
y >>= z -> pure x
= monad law
y >> pure x
* Okay, okay, so the actual definition of liftM uses return instead of pure. Whatever.
Interesting. For some reason I thought that the standard definition wasliftM = fmap, with the more restrictive type. With the real definition above, the wanted equation is much simpler to obtain :)
– chi
2 hours ago
1
@chi Even without it things aren't too bad:fmap f m = m >>= return . fis also a monad law (one of the oft-forgotten ones).
– Daniel Wagner
1 hour ago
1
That law itself follows from parametricity and the monad lawm >>= pure = m.
– dfeuer
38 mins ago
add a comment |
The other answer gets there eventually, but it takes a long-winded route. All that is actually needed are the definitions of liftM, const, and a single monad law: m1 >> m2 and m1 >>= _ -> m2 must be semantically identical. (Indeed, this is the default implementation of (>>), and it is rare to override it.) Then:
liftM (const x) y
= definition of liftM*
y >>= z -> pure (const x z)
= definition of const
y >>= z -> pure x
= monad law
y >> pure x
* Okay, okay, so the actual definition of liftM uses return instead of pure. Whatever.
Interesting. For some reason I thought that the standard definition wasliftM = fmap, with the more restrictive type. With the real definition above, the wanted equation is much simpler to obtain :)
– chi
2 hours ago
1
@chi Even without it things aren't too bad:fmap f m = m >>= return . fis also a monad law (one of the oft-forgotten ones).
– Daniel Wagner
1 hour ago
1
That law itself follows from parametricity and the monad lawm >>= pure = m.
– dfeuer
38 mins ago
add a comment |
The other answer gets there eventually, but it takes a long-winded route. All that is actually needed are the definitions of liftM, const, and a single monad law: m1 >> m2 and m1 >>= _ -> m2 must be semantically identical. (Indeed, this is the default implementation of (>>), and it is rare to override it.) Then:
liftM (const x) y
= definition of liftM*
y >>= z -> pure (const x z)
= definition of const
y >>= z -> pure x
= monad law
y >> pure x
* Okay, okay, so the actual definition of liftM uses return instead of pure. Whatever.
The other answer gets there eventually, but it takes a long-winded route. All that is actually needed are the definitions of liftM, const, and a single monad law: m1 >> m2 and m1 >>= _ -> m2 must be semantically identical. (Indeed, this is the default implementation of (>>), and it is rare to override it.) Then:
liftM (const x) y
= definition of liftM*
y >>= z -> pure (const x z)
= definition of const
y >>= z -> pure x
= monad law
y >> pure x
* Okay, okay, so the actual definition of liftM uses return instead of pure. Whatever.
edited 3 hours ago
answered 3 hours ago
Daniel WagnerDaniel Wagner
103k7161283
103k7161283
Interesting. For some reason I thought that the standard definition wasliftM = fmap, with the more restrictive type. With the real definition above, the wanted equation is much simpler to obtain :)
– chi
2 hours ago
1
@chi Even without it things aren't too bad:fmap f m = m >>= return . fis also a monad law (one of the oft-forgotten ones).
– Daniel Wagner
1 hour ago
1
That law itself follows from parametricity and the monad lawm >>= pure = m.
– dfeuer
38 mins ago
add a comment |
Interesting. For some reason I thought that the standard definition wasliftM = fmap, with the more restrictive type. With the real definition above, the wanted equation is much simpler to obtain :)
– chi
2 hours ago
1
@chi Even without it things aren't too bad:fmap f m = m >>= return . fis also a monad law (one of the oft-forgotten ones).
– Daniel Wagner
1 hour ago
1
That law itself follows from parametricity and the monad lawm >>= pure = m.
– dfeuer
38 mins ago
Interesting. For some reason I thought that the standard definition was
liftM = fmap, with the more restrictive type. With the real definition above, the wanted equation is much simpler to obtain :)– chi
2 hours ago
Interesting. For some reason I thought that the standard definition was
liftM = fmap, with the more restrictive type. With the real definition above, the wanted equation is much simpler to obtain :)– chi
2 hours ago
1
1
@chi Even without it things aren't too bad:
fmap f m = m >>= return . f is also a monad law (one of the oft-forgotten ones).– Daniel Wagner
1 hour ago
@chi Even without it things aren't too bad:
fmap f m = m >>= return . f is also a monad law (one of the oft-forgotten ones).– Daniel Wagner
1 hour ago
1
1
That law itself follows from parametricity and the monad law
m >>= pure = m.– dfeuer
38 mins ago
That law itself follows from parametricity and the monad law
m >>= pure = m.– dfeuer
38 mins ago
add a comment |
One more possible route, exploiting the applicative laws:
For instance I found that
y >> pure xcan be rewritten as follows [...]fmap (const id) y <*> pure x
That amounts to...
fmap (const id) y <*> pure x
pure ($ x) <*> fmap (const id) y -- interchange law of applicatives
($ x) <$> fmap (const id) y -- fmap in terms of <*>
fmap (($ x) . const id) y -- composition law of functors
fmap (const x) y
... which, as you noted, is the same as liftM (const x) y.
That this route requires only applicative laws and not monad ones reflects how (*>) (another name for (>>)) is an Applicative method.
add a comment |
One more possible route, exploiting the applicative laws:
For instance I found that
y >> pure xcan be rewritten as follows [...]fmap (const id) y <*> pure x
That amounts to...
fmap (const id) y <*> pure x
pure ($ x) <*> fmap (const id) y -- interchange law of applicatives
($ x) <$> fmap (const id) y -- fmap in terms of <*>
fmap (($ x) . const id) y -- composition law of functors
fmap (const x) y
... which, as you noted, is the same as liftM (const x) y.
That this route requires only applicative laws and not monad ones reflects how (*>) (another name for (>>)) is an Applicative method.
add a comment |
One more possible route, exploiting the applicative laws:
For instance I found that
y >> pure xcan be rewritten as follows [...]fmap (const id) y <*> pure x
That amounts to...
fmap (const id) y <*> pure x
pure ($ x) <*> fmap (const id) y -- interchange law of applicatives
($ x) <$> fmap (const id) y -- fmap in terms of <*>
fmap (($ x) . const id) y -- composition law of functors
fmap (const x) y
... which, as you noted, is the same as liftM (const x) y.
That this route requires only applicative laws and not monad ones reflects how (*>) (another name for (>>)) is an Applicative method.
One more possible route, exploiting the applicative laws:
For instance I found that
y >> pure xcan be rewritten as follows [...]fmap (const id) y <*> pure x
That amounts to...
fmap (const id) y <*> pure x
pure ($ x) <*> fmap (const id) y -- interchange law of applicatives
($ x) <$> fmap (const id) y -- fmap in terms of <*>
fmap (($ x) . const id) y -- composition law of functors
fmap (const x) y
... which, as you noted, is the same as liftM (const x) y.
That this route requires only applicative laws and not monad ones reflects how (*>) (another name for (>>)) is an Applicative method.
edited 33 mins ago
answered 1 hour ago
duplodeduplode
23.1k44987
23.1k44987
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55384267%2fis-x-pure-y-equivalent-to-liftm-const-y-x%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown