<div dir="ltr">I guess my question is, how to I type LHS so it is no more specialised as RHS in this case?</div><div class="gmail_extra"><br><div class="gmail_quote">On Sun, Jul 19, 2015 at 6:42 PM, Ivan Lazar Miljenovic <span dir="ltr"><<a href="mailto:ivan.miljenovic@gmail.com" target="_blank">ivan.miljenovic@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">My understanding is that when you have "LHS = RHS", you can replace<br>
any instance of LHS with RHS but you can't always do it the other way<br>
around, as the LHS might be more specialised (as in this case it is).<br>
<span class=""><br>
On 19 July 2015 at 18:08, Clinton Mead <<a href="mailto:clintonmead@gmail.com">clintonmead@gmail.com</a>> wrote:<br>
> Thanks for the CC Ivan, forgot to "reply all".<br>
><br>
> I guess I want the passed argument to stay polymorphic long enough to be<br>
> instanced inside the call.<br>
><br>
> Surely if "f x = g x x" then you should somehow be able to replace "g x x"<br>
> with "f x"?! That's basically what I'm getting at.<br>
><br>
><br>
><br>
> On Sun, Jul 19, 2015 at 5:54 PM, Ivan Lazar Miljenovic<br>
</span><span class="">> <<a href="mailto:ivan.miljenovic@gmail.com">ivan.miljenovic@gmail.com</a>> wrote:<br>
>><br>
>> (Re-CC'ing Cafe)<br>
>><br>
>> I think what's happening here is that when you do "apply f1 f1", the<br>
>> two c's and d's don't actually match with each other.<br>
>><br>
>> But when you do it with applyBoth, they *have* to match each other.<br>
>><br>
>> As a comparison, compare:<br>
>><br>
>> :t (read, read)<br>
>> (read, read) :: (Read a, Read a1) => (String -> a, String -> a1)<br>
>><br>
>> and<br>
>><br>
>> :t Control.Monad.join read<br>
>> Control.Monad.join (,) read :: Read a => (String -> a, String -> a)<br>
>><br>
>> I'm not sure how you could define such a function to do what you're<br>
>> requesting; my attempt is this:<br>
>><br>
>> applyBoth :: (forall a b a2 b2. arr a b -> arr a2 b2) -> D arr a b -><br>
>> D arr a2 b2<br>
>> applyBoth f = apply f f<br>
>><br>
>> but whilst ghci accepts it, I couldn't actually seem to use it (lots<br>
>> of errors about being unable to match types).<br>
>><br>
</span><span class="">>> On 19 July 2015 at 17:15, Clinton Mead <<a href="mailto:clintonmead@gmail.com">clintonmead@gmail.com</a>> wrote:<br>
>> > Thanks for your reply Ivan<br>
>> ><br>
</span>>> > Here's a full code example ( <a href="http://ideone.com/1K3Yhw" rel="noreferrer" target="_blank">http://ideone.com/1K3Yhw</a> ):<br>
<div><div class="h5">>><br>
>> ><br>
>> > ---<br>
>> ><br>
>> > data D c a b = D (c a b) (c b a)<br>
>> ><br>
>> > apply :: (c a b -> c a2 b2) -> (c b a -> c b2 a2) -> D c a b -> D c a2<br>
>> > b2<br>
>> > apply f1 f2 (D x y) = D (f1 x) (f2 y)<br>
>> ><br>
>> > applyBoth f = apply f f<br>
>> ><br>
>> > f :: Int -> String<br>
>> > f = show<br>
>> ><br>
>> > g :: String -> Int<br>
>> > g = read<br>
>> ><br>
>> > h :: Int -> Int<br>
>> > h = (*2)<br>
>> ><br>
>> > join :: (a -> b) -> (c -> d) -> ((a, c) -> (b, d))<br>
>> > join f g (x, y) = (f x, g y)<br>
>> ><br>
>> > x1 = D f g<br>
>> ><br>
>> > f1 = join h<br>
>> ><br>
>> > y1 = apply f1 f1 x1 -- This compiles<br>
>> > y2 = apply g g x1 where g = f1 -- Also works<br>
>> ><br>
>> > z1 = applyBoth f1 x1 -- This fails<br>
>> ><br>
>> > main = return ()<br>
>> ><br>
>> > ---<br>
>> ><br>
>> > You see, with "y1" and "y2", a different "f1" instantiation (is that the<br>
>> > right word) of "f1" is chosen. Even when I let "g = f1", each "g" passed<br>
>> > to<br>
>> > apply is different, the first operates on "Int -> String", the second,<br>
>> > "String -> Int".<br>
>> ><br>
>> > On the face of it, if:<br>
>> ><br>
>> > f x = g x x<br>
>> ><br>
>> > Then well, you should be able to replace "g x x" with "f x" wherever you<br>
>> > see<br>
>> > it.<br>
>> ><br>
>> > But it seems in this case this doesn't work. Surely Haskell doesn't<br>
>> > require<br>
>> > me to "repeat myself", and there's a way to write "applyBoth", instead<br>
>> > of<br>
>> > having to write "apply f f" (note the repetition of f) all the time?<br>
>> ><br>
>> > I assume there's some type signature I can give "applyBoth f" so it can<br>
>> > be<br>
>> > used just like "apply f f" but I can't work out what it is.<br>
>> ><br>
>> > On Sun, Jul 19, 2015 at 10:23 AM, Ivan Lazar Miljenovic<br>
</div></div>>> > <<a href="mailto:ivan.miljenovic@gmail.com">ivan.miljenovic@gmail.com</a>> wrote:<br>
<div><div class="h5">>><br>
>> >><br>
>> >> On 19 July 2015 at 10:13, Clinton Mead <<a href="mailto:clintonmead@gmail.com">clintonmead@gmail.com</a>> wrote:<br>
>> >> > Lets say I've got the following data type:<br>
>> >> ><br>
>> >> > data D c a b = D (c a b) (c b a)<br>
>> >> ><br>
>> >> > And I define a function to manipulate it:<br>
>> >> ><br>
>> >> > apply :: (c a b -> c a2 b2) -> (c b a -> c b2 a2) -> D c a b -> D c<br>
>> >> > a2<br>
>> >> > b2<br>
>> >> > apply f1 f2 (D x y) = D (f1 x) (f2 y)<br>
>> >> ><br>
>> >> > This is all fine. But I want a shorter function if (f1 = f2). So I<br>
>> >> > write:<br>
>> >> ><br>
>> >> > applyBoth f = apply f f<br>
>> >> ><br>
>> >> > I originally thought that if "apply f f" is valid, then logically<br>
>> >> > "applyBoth<br>
>> >> > f" should also be valid. But it seems that type inference results in<br>
>> >> > applyBoth only working for functions "c a a -> c a2 a2".<br>
>> >><br>
>> >> applyBoth f = apply f f<br>
>> >><br>
>> >> In apply, (f1 :: c a b -> c a2 b2) and (f2 :: c b a -> c b2 a2).<br>
>> >><br>
>> >> So for "apply f f" to typecheck, we must have that a ~ b and a2 ~ b2<br>
>> >> (as the above two type signatures must match since f1 = f2).<br>
>> >><br>
>> >> So we must have that (f :: c a a -> c a2 a2).<br>
>> >><br>
>> >> ><br>
>> >> > Is there a way to type "applyBoth" so it works for all functions that<br>
>> >> > would<br>
>> >> > work simply by repeating them twice in "apply"?<br>
>> >><br>
>> >> I'm not sure what you mean; what else would make sense?  Can you<br>
>> >> provide an example?<br>
>> >><br>
>> >> --<br>
>> >> Ivan Lazar Miljenovic<br>
</div></div>>> >> <a href="mailto:Ivan.Miljenovic@gmail.com">Ivan.Miljenovic@gmail.com</a><br>
<span class="">>> >> <a href="http://IvanMiljenovic.wordpress.com" rel="noreferrer" target="_blank">http://IvanMiljenovic.wordpress.com</a><br>
>> ><br>
>> ><br>
>><br>
>><br>
>><br>
>> --<br>
>> Ivan Lazar Miljenovic<br>
</span>>> <a href="mailto:Ivan.Miljenovic@gmail.com">Ivan.Miljenovic@gmail.com</a><br>
<span class="">>> <a href="http://IvanMiljenovic.wordpress.com" rel="noreferrer" target="_blank">http://IvanMiljenovic.wordpress.com</a><br>
><br>
><br>
<br>
<br>
<br>
--<br>
Ivan Lazar Miljenovic<br>
</span><a href="mailto:Ivan.Miljenovic@gmail.com">Ivan.Miljenovic@gmail.com</a><br>
<a href="http://IvanMiljenovic.wordpress.com" rel="noreferrer" target="_blank">http://IvanMiljenovic.wordpress.com</a><br>
</blockquote></div><br></div>