Working on Week 2 Homework 1, I tried to define a new type DuBool. The following is the relevant portion of the code, with the more traditional version commented out immediately above each line that uses DuBool.
newtype DuBool = DuBool (Bool,Bool)
PlutusTx.unstableMakeIsData ''DuBool
--
--
{-# INLINABLE mkValidator #-}
-- This should validate if and only if the two Booleans in the redeemer are equal!
-- mkValidator :: () -> (Bool, Bool) -> ScriptContext -> Bool
mkValidator :: () -> DuBool -> ScriptContext -> Bool
-- mkValidator _ _ _ = True -- FIX ME!
-- mkValidator _ (a,b) _ = traceIfFalse "Bools no match" $ a == b
mkValidator _ (DuBool d) _
| a==b = True
| otherwise = traceIfFalse "Bools no match" $ False
where (a,b) = d
--
--
data Typed
instance Scripts.ValidatorTypes Typed where
-- Implement the instance!
type instance DatumType Typed = ()
-- type instance RedeemerType Typed = (Bool,Bool)
type instance RedeemerType Typed = DuBool
--
--
typedValidator :: Scripts.TypedValidator Typed
-- typedValidator = undefined -- FIX ME!
typedValidator = Scripts.mkTypedValidator @Typed
$$(PlutusTx.compile [|| mkValidator ||])
$$(PlutusTx.compile [|| wrap ||])
where
-- wrap = Scripts.wrapValidator @() @(Bool,Bool)
wrap = Scripts.wrapValidator @() @DuBool
This does compile in the repl error-free, and does compile and run in the playground simulator, but failure occurs with evaluation when the grab validation step occurs in the simulator, with
, Slot 2: 00000000-0000-4000-8000-000000000000 {Wallet W7ce8}: Contract instance stopped with error: "WalletError (ValidationError (ScriptFailure (EvaluationError [\"PT1\"] \"CekEvaluationFailure\")))" ]
I went back and attempted to edit the "type GiftSchema =" section to use DuBool, as follows:
type GiftSchema =
Endpoint "give" Integer
-- .\/ Endpoint "grab" (Bool, Bool)
.\/ Endpoint "grab" DuBool
and then the grab definition...
-- grab :: forall w s e. AsContractError e => (Bool, Bool) -> Contract w s e ()
grab :: forall w s e. AsContractError e => DuBool -> Contract w s e ()
But now compilation in the repl fails (sorry that the color and alignment here does not match what I see in the repl).
Prelude Ledger.Scripts PlutusTx> :l src/Week02/Homework1c_jwb.hs [1 of 1] Compiling Week02.Homework1 ( src/Week02/Homework1c_jwb.hs, /Users/jwb/plutus/plutus-pioneer-program/code/week02/dist-newstyle/build/x86_64-osx/ghc-8.10.4.20210212/plutus-pioneer-program-week02-0.1.0.0/build/Week02/Homework1.o )src/Week02/Homework1c_jwb.hs:117:13: error: • No instance for (aeson-1.5.6.0:Data.Aeson.Types.FromJSON.FromJSON DuBool) arising from a use of ‘endpoint’ • In the expression: endpoint @"grab" grab In an equation for ‘grab'’: grab' = endpoint @"grab" grab In an equation for ‘endpoints’: endpoints = awaitPromise (give'
select
grab') >> endpoints where give' = endpoint @"give" give grab' = endpoint @"grab" grab | 117 | grab' = endpoint @"grab" grab | ^^^^^^^^^^^^^^^^^^^^^src/Week02/Homework1c_jwb.hs:119:1: error: • No instance for (Schema.ToSchema DuBool) arising from a use of ‘Playground.Schema.endpointsToSchemas’ • In the expression: Playground.Schema.endpointsToSchemas @((./) (Endpoint "give" Integer) (Endpoint "grab" DuBool)) In an equation for ‘schemas’: schemas = Playground.Schema.endpointsToSchemas @((./) (Endpoint "give" Integer) (Endpoint "grab" DuBool)) | 119 | mkSchemaDefinitions ''GiftSchema | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Failed, no modules loaded. Prelude Ledger.Scripts PlutusTx>
It appears that the entire code as written (including what I am leaving out for brevity) can convert (Bool,Bool) to JSON, but not DuBool. I am wondering if there is a simple change, perhaps to the imports, {-# LANGUAGE ... #-}, instantiation, etc. that would incorporate this functionality?
Clearly this is not needed to "solve" homework 1 of week 2, but I do believe it is a valid programmatic approach that will be useful going forward. And I think I am very close. Thanks in advance!
=============================================================
Kurt Sys provided an extremely helpful partial answer. A few rounds of trial and error in the repl led me to this compiling and working-in-the-simulator solution. I've left a comment trail to help anyone else following along.
-- import Playground.Contract (printJson, printSchemas, ensureKnownCurrencies, stage) import Playground.Contract (printJson, printSchemas, ensureKnownCurrencies, stage, Generic, FromJSON, ToJSON, ToSchema) -- -- newtype DuBool = DuBool (Bool,Bool) data DuBool = DuBool { b1 :: Bool ,b2 :: Bool } deriving (Generic, FromJSON, ToJSON, ToSchema) PlutusTx.unstableMakeIsData ''DuBool -- {-# INLINABLE mkValidator #-} -- This should validate if and only if the two Booleans in the redeemer are equal! -- mkValidator :: () -> (Bool, Bool) -> ScriptContext -> Bool mkValidator :: () -> DuBool -> ScriptContext -> Bool -- mkValidator _ _ _ = True -- FIX ME! -- mkValidator _ (DuBool (a,b)) _ = traceIfFalse "Bools no match" $ a == b -- mkValidator _ (a,b) _ = traceIfFalse "Bools no match" $ a == b -- mkValidator _ (DuBool d) _ mkValidator _ (DuBool a b) _ | a==b = True | otherwise = traceIfFalse "Bools no match" $ False -- where (a,b) = d
Now I need to understand the difference between "data" and "newtype".