<div dir="ltr"><div>Avoiding the name class for the moment by qualifying, it seems:<br></div><div><br></div><div>applyBoth = Control.Monad.join apply<br></div><div class="gmail_extra"><br></div><div class="gmail_extra">has the same issue<br><br><div class="gmail_quote">On Sun, Jul 19, 2015 at 7:03 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"><span class="">On 19 July 2015 at 18:51, Clinton Mead <<a href="mailto:clintonmead@gmail.com">clintonmead@gmail.com</a>> wrote:<br>
> I guess my question is, how to I type LHS so it is no more specialised as<br>
> RHS in this case?<br>
<br>
</span>I don't believe you can.<br>
<span class=""><br>
><br>
> On Sun, Jul 19, 2015 at 6:42 PM, Ivan Lazar Miljenovic<br>
</span><span class="">> <<a href="mailto:ivan.miljenovic@gmail.com">ivan.miljenovic@gmail.com</a>> wrote:<br>
>><br>
>> 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>
>><br>
</span><span class="">>> 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<br>
>> > 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>
>> >> ><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<br>
>> >> > 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<br>
>> >> > the<br>
>> >> > right word) of "f1" is chosen. Even when I let "g = f1", each "g"<br>
>> >> > passed<br>
>> >> > to<br>
>> >> > apply is different, the first operates on "Int -> String", the<br>
>> >> > 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<br>
>> >> > 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",<br>
>> >> > 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<br>
>> >> > 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>
>><br>
>> >><br>
>> >> >><br>
>> >> >> On 19 July 2015 at 10:13, Clinton Mead <<a href="mailto:clintonmead@gmail.com">clintonmead@gmail.com</a>><br>
<div><div class="h5">>> >> >> 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<br>
>> >> >> > 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<br>
>> >> >> > 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<br>
>> >> >> > 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>
<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></div>