Say I have a choice that takes an integer that represents a count and I want to create a contract that number of times, i.e. execute some block of code that many times.
In Ruby for example this might look like this:
n.times do
#run some code here
end
How do I achieve this in DAML?
TLDR
To apply a ledger operation N times the easiest way is to use the replicateA function from DA.Action.
Example
daml 1.2
module ReplicateDaml
where
import DA.Action
template Demo
with
sig: Party
total: Int
where
signatory sig
testReplicate = scenario do
p <- getParty "party"
let
total = 10
p `submit` replicateA total $ create Demo with sig=p; total
Discussion
The type signature for replicateA is:
-- | `replicateA n act` performs the action n times, gathering the results.
replicateA : (Applicative m) => Int -> m a -> m [a]
You can read this as:
This function supports any type m that has an instance (implementation) for the Applicative typeclass (api or interface).
Its first parameter is an Int
Its second is an 'effect' of the type m that provides a value of type a
It returns the result of repeating the effect N times, collecting the results in a list
The create you describe is of type: Update (ContractId a); and as Update instantiates (has an implementation for) the Applicative typeclass you can use any function that works on Applicative's on Update's — which naturally includes replicateA.
When used this way, substitute Update for m and (ContractId t) for a in the type signature, so:
replicateA : Int -> Update (ContractId t) -> Update [ContractId t]
Related
I am working on the Haskell project,
For the error checking, I need to take care of any function call having too many or too few arguments, but I currently have no idea for it.Hoping to get same hints to start.
Unless one uses some form of advanced ad hoc polymorphism like the printf :: PrintfType r => String -> r does, the compiler will notice.
Indeed, if you have a function like:
add :: Int -> Int -> Int
add = (+)
if you call it with three parameters, like add 2 4 5, then this will raise an error. This will happen, since add 2 4 5, or more canonical ((add 2) 4) 5, will try to eventually make a call to an item that is an Int. Indeed add 2 has type add 2 :: Int -> Int, and thus (add 2) 4 has type (add 2) 4 :: Int, so since that is not function, the compiler will raise an error:
Prelude> add 2 4 5
<interactive>:5:1: error:
• Couldn't match expected type ‘Integer -> t’
with actual type ‘Int’
• The function ‘add’ is applied to three arguments,
but its type ‘Int -> Int -> Int’ has only two
In the expression: add 2 4 5
In an equation for ‘it’: it = add 2 4 5
• Relevant bindings include it :: t (bound at <interactive>:5:1)
It thus says it expected a type (Integer -> t, although the Integer here is due to type defaulting), but got an Int instead. So that is not possible.
Calling a function with "too few" parameters is not really possible, since if you call it with too few, you simply generate a function that expects to take the next parameter. This is the idea behind currying [Haskell-wiki]. Indeed, if the type of add 2 is:
Prelude> :t add 2
add 2 :: Int -> Int
It is a function that expects the following parameter. It is possible that this will clash with another function that expects an Int, but then you will get a similar exception except that the expected will be a non-function (Int) for example, and the actual type is a function, so something like:
• Couldn't match expected type ‘Int’
with actual type ‘Integer -> t’
Haskell's type system will thus error in case you call a function with too much arguments, or when you use the result of a function with too few arguments.
Note that strictly speaking in Haskell every function only takes one parameter. If you do not provide one, then the outcome is still a function, if you provide one, you make a function call, but that function can produce another function thus expects the next parameter.
The reason that printf can take one, two, or more parameters, is because of the instances of the PrintfType type class. This can be an IO a that will thus then print the result of the formatted string, or a function (PrintfArg a, PrintfType r) => a -> r that thus will take a parameter of the PrintfArg type, and return another PrintfType type. It can thus each time specialize in an extra function if another function is necessary. But this thus emulates a variadic function, where you can pass an arbitrary number of parameters.
Is it possible in DAML to use a map-like function to iterate over of list of contractids, retrieve them and execute a choice on each? This appears to be limited in DAML by the way everything needs to be wrapped in a single Update when executing a choice.
Here's an example of what I've attempted (noting the issues):
exerciseChoice: ContractId ContractB -> Update (ContractId ContractB)
exerciseChoice contractB = do (exercise contractB UpdateB with newText = "test")
template ContractA
with
party : Party
contracts: [ContractId ContractB]
where
signatory party
controller party can
nonconsuming UpdateA : [Update (ContractId ContractB)]
with newText : Text
do
-- a <- create ContractB with party = party; text = newText
-- a2 <- exerciseChoice a
-- return [a2] #these lines work fine
return map exerciseChoice contracts
-- #this doesn't work due to DAML implicitly adding Update before return definition
-- i.e. DAML expects type 'Update [Update (ContractId ContractB)]' based on this signature
-- we need a function which converts something like:
-- '[Update (ContractId ContractB)] -> Update [ContractId ContractB]'
template ContractB
with
party : Party
text: Text
where
signatory party
controller party can
UpdateB: ContractId ContractB
with newText: Text
do create this with text = newText
If this can be solved, can you also explain why when returning multiple tuples in DAML they seem to implicitly cast from (Update (ContractId A), Update (ContractId B)) to Update (ContractId A, ContractId B)?
The function map has type (a -> b) -> [a] -> [b] so map exerciseChoice contracts will have type [Update (ContractId ContractB)]. Turning a list of actions into a single action is conceptually simple. The resulting action is the action of performing each action in the list in sequence. And indeed, there is a function for that: sequence : (Applicative m) => [m a] -> m [a]. Update is an applicative so you could write sequence (map exerciseChoice contracts). However, this is such a common task that there is a specialised function mapA : (Applicative m) => (a -> m b) -> [a] -> m [b].
mapA exerciseChoice contracts should do the trick.
[...] a pair of functions tofun : int -> ('a -> 'a) and fromfun : ('a -> 'a) ->
int such that (fromfun o tofun) n evaluates to n for every n : int.
Anyone able to explain to me what this is actually asking for? I'm looking for more of an explanation of that than an actual solution to this.
What this is asking for is:
1) A higher-order function tofun which when given an integer returns a polymorphic function, one which has type 'a->'a, meaning that it can be applied to values of any type, returning a value of the same type. An example of such a function is:
- fun id x = x;
val id = fn : 'a -> 'a
for example, id "cat" = "cat" and id () = (). The later value is of type unit, which is a type with only 1 value. Note that there is only 1 total function from unit to unit (namely, id or something equivalent). This underscores the difficulty with coming up with defining tofun: it returns a function of type 'a -> 'a, and other than the identity function it is hard to think of other functions. On the other hand -- such functions can fail to terminate or can raise an error and still have type 'a -> 'a.
2) fromfun is supposed to take a function of type 'a ->'a and return an integer. So e.g. fromfun id might evaluate to 0 (or if you want to get tricky it might never terminate or it might raise an error)
3) These are supposed to be inverses of each other so that, e.g. fromfun (tofun 5) needs to evaluate to 5.
Intuitively, this should be impossible in a sufficiently pure functional language. If it is possible in SML, my guess is that it would be by using some of the impure features of SML (which allow for side effects) to violate referential transparency. Or, the trick might involve raising and handling errors (which is also an impure feature of SML). If you find an answer which works in SML it would be interesting to see if it could be translated to the annoyingly pure functional language Haskell. My guess is that it wouldn't translate.
You can devise the following property:
fun prop_inverse f g n = (f o g) n = n
And with definitions for tofun and fromfun,
fun tofun n = ...
fun fromfun f = ...
You can test that they uphold the property:
val prop_test_1 =
List.all
(fn i => prop_inverse fromfun tofun i handle _ => false)
[0, ~1, 1, valOf Int.maxInt, valOf Int.minInt]
And as John suggests, those functions must be impure. I'd also go with exceptions.
I wrote a custom pretty printer for Core Haskell in order to better study Core's structure. The gist of this pretty printer is that it takes a CoreModule and includes data constructors in the output, which the default Outputable implementation does not seem to do.
Here is the code of the module that I am running the pretty printer on:
module Bar2 where
add :: Int -> Int -> Int
add a b = a + b
add2 a b = a + b
Here is the pretty printer output:
------------------------------- Module Metadata --------------------------------
Module { "main" :: modulePackageId, "Bar2" :: moduleName }
-------------------------------- Type Bindings ---------------------------------
[r0 :-> Identifier ‘add’, rjH :-> Identifier ‘add2’]
-------------------------------- Core Bindings ---------------------------------
NonRec (Id "add2")
(Lam (TyVar "a")
(Lam (Id "$dNum")
(Lam (Id "a1")
(Lam (Id "b")
(App (App (App (App (Var (Id "+"))
(Type (TyVar (TyVar "a"))))
(Var (Id "$dNum")))
(Var (Id "a1")))
(Var (Id "b")))))))
NonRec (Id "add")
(Lam (Id "a")
(Lam (Id "b")
(App (App (App (App (Var (Id "+"))
(Type (TyConApp (Int) [])))
(Var (Id "$fNumInt")))
(Var (Id "a")))
(Var (Id "b")))))
--------------------------------- Safe Haskell ---------------------------------
Safe
------------------------------------- End --------------------------------------
What is confusing to me is that in both instances, Core appears to be applying a type variable, or a type constructor to the + function, as well as some $dNum or $fNumInt before taking in the arguments.
For the add function, the type is also explicitly given, while the add2 is left up to compiler inference. This also seems to affect the number of arguments that the chain of lambda functions requires for evaluation, with add needing 2 while add2 requiring 4.
What does this all mean?
Core is pretty much SystemF (technically SystemFC). In SystemF, type variables also need to be arguments to the function. In your example, Haskell infers that
add2 :: Num a => a -> a -> a
add2 a b = a + b
That explains the TyVar "a" argument to add2.
Also, Haskell has to find a way to dispatch to the 'right' set of Num functions depending on what the type of the arguments a and b is. It does that by having a dictionary argument for each type class constraint. That's the Id $dNum argument. In the case of add, Haskell already knows which dictionary the appropriate (+) function can be found since it knows it knows the operation is on Int (so it doesn't need to be passed in: it's just $fNumInt).
Essentially what happens under the hood is that for each typeclass Haskell makes a record data $d<Class> = ... with fields that are the functions inside the typeclass. Then, for each instance, it makes another $f<Class><Type> :: $d<Class>. This is explained in more detail here
Here is another excellent answer describing Core related things.
In GHC 8.x you can play with type arguments in Haskell as well, similarly to Core. Here's an example with some more annotations, based on the posted code.
add :: Int -> Int -> Int
add a b = (+) # Int a b
The (+) # Int specializes the polymorphic (+) operator so that it works on type Int.
In Core, you also see the typeclass dictionary being passed around $fNumInt.
add2 :: forall n. Num n => n -> n -> n
add2 a b = (+) # n a b
This is basically the same, except that n is not known.
In Core, add2 takes a hidden "type-valued" argument n (confusingly called a in the posted example, i.e. (Lam (TyVar "a") ...), which is then forwarded to (+) as a type argument. Since the dictionary is now unknown, in Core there is another hidden argument: the dictionary has to be passed by the caller of add2, which then forwards it to (+). This additional argument is called $dNum (See (Lam (Id "$dNum") ...).
cube (x,y,z) =
filter (pcubes x) cubes
cubes = [(a,b,c) | a <- [1..30],b <- [1..30],c <- [1..30]]
pcubes x (b,n,m) = (floor(sqrt(b*n)) == x)
so this code works, cubes makes a list of tuples,pcubes is used with filter to filter all the cubes in which floor(sqrt(b*n)) == x is satisfied,but the person who has modified my code wrote pcubes x in filter (pcubes x) cubes,how does this work.pcubes x makes a function that will initial the cubes x (b,n,m) that will take in a tuple and output a bool.the bool will be used in the filter function. How does this sort of manipulation happen? how does pcubes x access the (b,n,m) part of the function?
In Haskell, we don't usually use tuples (ie: (a,b,c)) to pass arguments to functions. We use currying.
Here's an example:
add a b = a + b
Here add is a function that takes a number, the returns another function that takes a number, then returns a number. We represent it's type as so:
add :: Int -> (Int -> Int)
Because of the way -> behaves, we can remove the parentheses in this case:
add :: Int -> Int -> Int
It is called like this:
(add 1) 2
but because of the way application works, we can just write:
add 1 2
Doesn't that look like our definition above, of the form add a b...?
Your function pcubes is similar. Here's how I'd write it:
pcubes x (b,n,m) = floor (sqrt (b*n)) == x
And as someone else said, it's type could be represented as:
pcubes :: Float -> (Float, Float, Float) -> Bool
When we write pcubes 1 the type becomes:
pcubes 1 :: (Float, Float, Float) -> Bool
Which, through currying, is legal, and can quite happily be used elsewhere.
I know, this is crazy black functional magic, as it was for me, but before long I guarantee you'll never want to go back: curried functions are useful.
A note on tuples: Expressions like (a,b,c) are data . They are not purely function-argument expressions. The fact that we can pull it into a function is called pattern matching, though it's not my turn to go into that.