<div dir="ltr">You are correct that GHC sees two different `r`'s here. I don't think you can get around using ScopedTypeVariables (which I wouldn't care about). The difference in annotating the expression is that you need an (explicit) forall. I actually don't know why the pattern type annotation doesn't need this... <div><br></div><div><div>saveToDb :: forall r. (FromJSON r, ToRow r) => LazyByteString -> (r -> IO ()) -> IO ()</div><div>saveToDb json processRow =</div><div>    case eitherDecode json of</div><div>        Left _err -> return () -- for simplicity</div><div>        Right rows -> forM_ (rows :: [r]) processRow</div></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Oct 15, 2015 at 10:17 PM, Amit Aryeh Levy <span dir="ltr"><<a href="mailto:amit@amitlevy.com" target="_blank">amit@amitlevy.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Thanks Adam!<br>
<br>
Vector does make more sense (i'll continue to use lists in this thread<br>
just for simplicity, since I don't think it matters for the higher level<br>
problem).<br>
<br>
`forM_ (objs :: Type) ....` seems like exactly the right solution in the<br>
simple case. However, it doesn't seem to work if I try to write a more<br>
general function. For example:<br>
<br>
```<br>
class ToRow r<br>
<br>
saveToDb :: FromJSON r, ToRow r => ByteString -> (tr -> IO ()) -> IO ()<br>
saveToDb json processRow =<br>
    case eitherDecode json of<br>
        Left err => return () -- for simplicity<br>
        Right rows => forM_ (rows :: [r]) processRow<br>
```<br>
<br>
GHC complains about two things:<br>
<br>
    1. eitherDecode can't determine which `FromJSON` instance to use<br>
    2. "Couldn't match expected type [r1] with actual type a0" in `rows<br>
:: [r]`.<br>
<br>
I think the issue is that GHC is not relating `rows :: [r]` to `FromJSON<br>
r` in the function type.<br>
<br>
Falling back to either ScopedTypeVariables or explicit<br>
contruction/deconstruction of the list works:<br>
<br>
```<br>
class ToRow r<br>
<br>
saveToDb :: FromJSON r, ToRow r => ByteString -> (tr -> IO ()) -> IO ()<br>
saveToDb json processRow =<br>
    case eitherDecode json of<br>
        Left err => return () -- for simplicity<br>
        Right (rows :: [r]) => forM_ rows processRow<br>
```<br>
<br>
Thoughts?<br>
<br>
Thanks!<br>
<span class="HOEnZb"><font color="#888888">Amit<br>
</font></span><br>
P.S.<br>
Thanks to Felipe for politely reminding me that these are lists we are<br>
dealing with, not arrays!<br>
<div class="HOEnZb"><div class="h5"><br>
On 10/15/2015 02:27 PM, Adam Bergmark wrote:<br>
> If you care about performance you may - I haven't benchmarked - want to use<br>
> Vector instead of lists here since that's what aeson uses internally. Then<br>
> it's pretty handy that you can still use forM_.<br>
><br>
> It's possible that the list pattern deconstruction and list construction<br>
> gets optimized away, my gut says you need -O2 for that to happen. Here's a<br>
> good explanation on how to dump and read core so you can check for yourself<br>
> what happens in this case:<br>
> <a href="http://stackoverflow.com/questions/6121146/reading-ghc-core" rel="noreferrer" target="_blank">http://stackoverflow.com/questions/6121146/reading-ghc-core</a> . Either way<br>
> it's definitiely not less efficient to annotate the type instead. You don't<br>
> need ScopedTypeVariables here, you can write the type inside an expression<br>
> instead: `forM (objs :: Type) [...]`<br>
><br>
> HTH,<br>
> Adam<br>
><br>
><br>
> On Thu, Oct 15, 2015 at 7:16 PM, Amit Aryeh Levy <<a href="mailto:amit@amitlevy.com">amit@amitlevy.com</a>> wrote:<br>
><br>
>> I've been running into a relatively small but frequent annoyance with<br>
>> base >= 4.8 (GHC 7.10). `Control.Monad.foldM_`, `Control.Monad.mapM_`<br>
>> and `Control.Monad.forM_` are generalized traverse over any `Foldable a`<br>
>> rather than just arrays (`[a]`).<br>
>><br>
>>  This is great, except I'm finding that, for a lot of my code that works<br>
>> well in previous versions, I need to specialize the argument to `[a]`<br>
>> now. If other people are encoutering a similar patter, I wonder what are<br>
>> your best practices for doing this: ScopedTypeVariables? Deconstruct the<br>
>> reconstruct the array? ...<br>
>><br>
>>  The most common example is when I deserialize a JSON array with aeson<br>
>> and want to traverse over that array (say, to store the objects to a DB):<br>
>><br>
>>  ```<br>
>> let objArray = eitherDecode myjson<br>
>> case objArray of<br>
>>     Left err -> ...<br>
>>     Right (objs :: [MyObjType]) -><br>
>>         forM_ objs $ \obj -> saveToDb obj<br>
>>  ```<br>
>><br>
>> ​The above fix requires `ScopedTypeVariables` (which is probably OK).<br>
>> Another option is to deconstruct and reconstruct the list:<br>
>><br>
>> ```<br>
>> Right (o:objs) -><br>
>>     forM_ (o:objs) $ \obj -> saveToDb obj<br>
>> ```<br>
>><br>
>> Does this get optimized away?<br>
>><br>
>> Penny for your thoughts?<br>
>><br>
>> Cheers!<br>
>> Amit<br>
>><br>
>><br>
>> _______________________________________________<br>
>> Haskell-Cafe mailing list<br>
>> <a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br>
>> <a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe</a><br>
>><br>
>><br>
<br>
<br>
</div></div></blockquote></div><br></div>