user5602: In homework of week4, I refactored my solution:
payTrace :: Integer -> Integer -> EmulatorTrace ()
payTrace payment1 payment2 =  do
contract1 <- activateContractWallet (knownWallet 1) payContract
let pkh2 = mockWalletPaymentPubKeyHash $ knownWallet 2
callEndpoint @"pay" contract1 $ PayParams
   {
       ppRecipient = pkh2
   ,   ppLovelace = payment1
   }
void $ Emulator.waitNSlots 1
callEndpoint @"pay" contract1 $ PayParams
   {
       ppRecipient = pkh2
   ,   ppLovelace = payment2
   }
void $ Emulator.waitNSlots 1

to:
payTrace :: Integer -> Integer -> EmulatorTrace ()
payTrace payment1 payment2 =  do
contract1 <- activateContractWallet (knownWallet 1) payContract
let pkh2 = mockWalletPaymentPubKeyHash $ knownWallet 2
    payTo :: (Member RunContract effs) => PaymentPubKeyHash -> Integer -> Eff effs ()
    payTo pkh amount = callEndpoint @"pay" contract1 $ PayParams
       {
           ppRecipient = pkh
       ,   ppLovelace = amount
       }
payTo pkh2 payment1
void $ Emulator.waitNSlots 1
payTo pkh2 payment2
void $ Emulator.waitNSlots 1

(https://gitlab.com/moment-4/courses/plutus-pioneer/plutus-pioneer-program/-/blob/week04/code/week04/src/Week04/Homework.hs)
However, there are still 2 things I don't like about my current solution:

I'd prefer to put the payTo function in the where clause, but that doesn't seem to work properly (although I think I'm close thanks to Luis (https://discord.com/channels/826816523368005654/834340082273878046/942064349831381042). How would one define it in the where clause? (The solution of Luis put me on the right track, but I still can't get it right)

I still get compiler warnings about the type. How to define the type of the function properly, so I can get rid of the warnings as well?


src/Week04/Homework.hs:46:18: warning: [-Wsimplifiable-class-constraints]
    • The constraint ‘Member RunContract effs’ matches
        instance (Data.OpenUnion.Internal.FindElem t r,
                  Data.OpenUnion.Internal.IfNotFound t r r) =>
                 Member t r
          -- Defined in ‘Data.OpenUnion.Internal’
      This makes type inference for inner bindings fragile;
        either use MonoLocalBinds, or simplify it using the instance
    • In the type signature:
        payTo :: (Member RunContract effs) =>
                 PaymentPubKeyHash -> Integer -> Eff effs ()
      In the expression:
        do contract1 <- activateContractWallet (knownWallet 1) payContract
           let pkh2 = mockWalletPaymentPubKeyHash $ knownWallet 2
               payTo ::
                 (Member RunContract effs) =>
                 PaymentPubKeyHash -> Integer -> Eff effs ()
               ....
           payTo pkh2 payment1
           void $ Emulator.waitNSlots 1
           ....
      In an equation for ‘payTrace’:
          payTrace payment1 payment2
            = do contract1 <- activateContractWallet
                                (knownWallet 1) payContract
                 let pkh2 = ...
                     ....
                 payTo pkh2 payment1
                 ....
   |
46 |         payTo :: (Member RunContract effs) => PaymentPubKeyHash -> Integer -> Eff effs ()
   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Ok, 8 modules loaded.


Thanks!

user5565: I don't know if this is what you expect but there are three ways to get rid of warnings:

add {-# LANGUAGE MonoLocalBinds     #-}, like the warning hints
don't give a type for payTo and let Haskell infer it
if things worked before, the body of payTo was fine in the EmulatorTrace monad, so you could go for payTo :: PaymentPubKeyHash -> Integer -> EmulatorTrace ()

I'm not particularly fond of the idea of moving the function in a where clause if it depends on something you obtain in the body of the bigger function. You could consider adding another parameter and passing contract1 as an argument, and then you can move it to where.

5602: <p>In homework of week4, I refactored my solution:</p>
<pre><code>payTrace :: Integer -&gt; Integer -&gt; EmulatorTrace ()
payTrace payment1 payment2 =  do
contract1 &lt;- activateContractWallet (knownWallet 1) payContract
let pkh2 = mockWalletPaymentPubKeyHash $ knownWallet 2
callEndpoint @&quot;pay&quot; contract1 $ PayParams
   {
       ppRecipient = pkh2
   ,   ppLovelace = payment1
   }
void $ Emulator.waitNSlots 1
callEndpoint @&quot;pay&quot; contract1 $ PayParams
   {
       ppRecipient = pkh2
   ,   ppLovelace = payment2
   }
void $ Emulator.waitNSlots 1
</code></pre>
<p>to:</p>
<pre><code>payTrace :: Integer -&gt; Integer -&gt; EmulatorTrace ()
payTrace payment1 payment2 =  do
contract1 &lt;- activateContractWallet (knownWallet 1) payContract
let pkh2 = mockWalletPaymentPubKeyHash $ knownWallet 2
    payTo :: (Member RunContract effs) =&gt; PaymentPubKeyHash -&gt; Integer -&gt; Eff effs ()
    payTo pkh amount = callEndpoint @&quot;pay&quot; contract1 $ PayParams
       {
           ppRecipient = pkh
       ,   ppLovelace = amount
       }
payTo pkh2 payment1
void $ Emulator.waitNSlots 1
payTo pkh2 payment2
void $ Emulator.waitNSlots 1
</code></pre>
<p>(<a href="https://gitlab.com/moment-4/courses/plutus-pioneer/plutus-pioneer-program/-/blob/week04/code/week04/src/Week04/Homework.hs" rel="nofollow noreferrer">https://gitlab.com/moment-4/courses/plutus-pioneer/plutus-pioneer-program/-/blob/week04/code/week04/src/Week04/Homework.hs</a>)</p>
<p>However, there are still 2 things I don't like about my current solution:</p>
<ol>
<li><p>I'd prefer to put the <code>payTo</code> function in the where clause, but that doesn't seem to work properly (although I think I'm close thanks to Luis (<a href="https://discord.com/channels/826816523368005654/834340082273878046/942064349831381042" rel="nofollow noreferrer">https://discord.com/channels/826816523368005654/834340082273878046/942064349831381042</a>). How would one define it in the where clause? (The solution of Luis put me on the right track, but I still can't get it right)</p>
</li>
<li><p>I still get compiler warnings about the type. How to define the type of the function properly, so I can get rid of the warnings as well?</p>
</li>
</ol>
<pre><code>src/Week04/Homework.hs:46:18: warning: [-Wsimplifiable-class-constraints]
    • The constraint ‘Member RunContract effs’ matches
        instance (Data.OpenUnion.Internal.FindElem t r,
                  Data.OpenUnion.Internal.IfNotFound t r r) =&gt;
                 Member t r
          -- Defined in ‘Data.OpenUnion.Internal’
      This makes type inference for inner bindings fragile;
        either use MonoLocalBinds, or simplify it using the instance
    • In the type signature:
        payTo :: (Member RunContract effs) =&gt;
                 PaymentPubKeyHash -&gt; Integer -&gt; Eff effs ()
      In the expression:
        do contract1 &lt;- activateContractWallet (knownWallet 1) payContract
           let pkh2 = mockWalletPaymentPubKeyHash $ knownWallet 2
               payTo ::
                 (Member RunContract effs) =&gt;
                 PaymentPubKeyHash -&gt; Integer -&gt; Eff effs ()
               ....
           payTo pkh2 payment1
           void $ Emulator.waitNSlots 1
           ....
      In an equation for ‘payTrace’:
          payTrace payment1 payment2
            = do contract1 &lt;- activateContractWallet
                                (knownWallet 1) payContract
                 let pkh2 = ...
                     ....
                 payTo pkh2 payment1
                 ....
   |
46 |         payTo :: (Member RunContract effs) =&gt; PaymentPubKeyHash -&gt; Integer -&gt; Eff effs ()
   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Ok, 8 modules loaded.

</code></pre>
<p>Thanks!</p>
 5565: <p>I don't know if this is what you expect but there are three ways to get rid of warnings:</p>
<ol>
<li>add <code>{-# LANGUAGE MonoLocalBinds     #-}</code>, like the warning hints</li>
<li>don't give a type for <code>payTo</code> and let Haskell infer it</li>
<li>if things worked before, the body of <code>payTo</code> was fine in the <code>EmulatorTrace</code> monad, so you could go for <code>payTo :: PaymentPubKeyHash -&gt; Integer -&gt; EmulatorTrace ()</code></li>
</ol>
<p>I'm not particularly fond of the idea of moving the function in a <code>where</code> clause if it depends on something you obtain in the body of the bigger function. You could consider adding another parameter and passing <code>contract1</code> as an argument, and then you can move it to <code>where</code>.</p>
