<div dir="ltr">Thanks for the CC Ivan, forgot to "reply all".<div><br></div><div>I guess I want the passed argument to stay polymorphic long enough to be instanced inside the call.</div><div><br></div><div>Surely if "f x = g x x" then you should somehow be able to replace "g x x" with "f x"?! That's basically what I'm getting at.</div><div><br></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Sun, Jul 19, 2015 at 5:54 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">(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>
<span class="">applyBoth f = apply f f<br>
<br>
</span>but whilst ghci accepts it, I couldn't actually seem to use it (lots<br>
of errors about being unable to match types).<br>
<span class=""><br>
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>
> 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 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 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 see<br>
> it.<br>
><br>
> But it seems in this case this doesn't work. Surely Haskell doesn't require<br>
> me to "repeat myself", and there's a way to write "applyBoth", instead 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 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>
>> 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 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>
>> <a href="http://IvanMiljenovic.wordpress.com" rel="noreferrer" target="_blank">http://IvanMiljenovic.wordpress.com</a><br>
<div class="HOEnZb"><div class="h5">><br>
><br>
<br>
<br>
<br>
--<br>
Ivan Lazar Miljenovic<br>
<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>
</div></div></blockquote></div><br></div>