Declaring a property test in an interface using a constant defined in the same interface - pact-lang

I am trying to verify a module I have implemented against an interface, where the interface includes a model for a specific function. That model relies on a constant, also defined in the interface. It looks like this:
(interface my-interface
(defconst MAX:decimal 100.0)
(defun id:decimal (amount:decimal)
#model [(property (<= amount MAX))]))
(module my-module GOVERNANCE
(implements my-interface)
(defcap GOVERNANCE ()
true)
(defun id:decimal (amount:decimal)
(enforce (<= amount my-interface.MAX)
(format "{} exceeds the maximum ({})" [ amount, my-interface.MAX ]))
amount))
This results in a failure when running (verify "my-module") a REPL file like this:
(begin-tx)
(load "./tester.pact")
(commit-tx)
(verify "my-module")
Specifically, the error:
:OutputFailure: could not parse (<= amount MAX): couldn't find property variable MAX
If I replace my model with this code then it works:
#model [(property (<= amount 100.0))]
I thought perhaps I needed to qualify the constant, but this fails as well:
#model [(property (<= amount my-interface.MAX))]
with the error message:
:OutputFailure: : could not parse (<= amount my-interface.MAX): in my-interface.MAX, expected property
Oddly enough, I can use the constant if I declare an invariant in a (defschema):
(interface my-interface
(defconst MAX:decimal 100.0)
(defschema my-schema
#model [(invariant (<= total MAX))]
total:decimal))
But, alas, I am not able to use the constant when declaring property tests in functions in the interface. So: how can I refer to a constant defined in my interface in a property test in the same interface?

Related

How do Pact interfaces provide abstraction similar to Haskell type classes?

The Pact documentation mentions that interfaces in Pact allow for abstraction similar to Haskell's type classes:
When a module issues an implements, then that module is said to ‘implement’ said interface, and must provide an implementation . This allows for abstraction in a similar sense to Java’s interfaces, Scala’s traits, Haskell’s typeclasses or OCaML’s signatures. Multiple interfaces may be implemented in a given module, allowing for an expressive layering of behaviors.
I understand that you can write an interface (this corresponds with declaring a class in Haskell), and then you can implement the interface for one or more modules (this corresponds with an instance in Haskell). For example:
-- This corresponds with declaring an interface
class Show a where
show :: a -> String
-- This corresponds with implementing an interface
instance Show Bool where
show True = "True"
show False = "False"
However, the great value of a Haskell type class is that you can then abstract over it. You can write a function that takes any value so long as it is an instance of Show:
myFunction :: (Show a) => a -> ...
myFunction = ...
What is the corresponding concept in Pact? Is there a way to accept any module as a dependency, so long as it implements the interface? If not, how does this open up abstraction "in a similar sense to Haskell's type classes"?
I think your question may be conflating typeclasses with type variables and universal quantification. Typeclasses give you a common interface like show that can be used on any type (or in this case, module) that supports them. Universal quantification lets you write generic algorithms that work for any Show instance.
Pact provides the former, but not the latter. The main utility is in giving your module a template to work against, and anyone who knows the interface will be able to use your module. This makes "swapping implementations" possible, but doesn't open the door to "generic algorithms". For that we'd need some way of saying "For all modules that implement interface"...
UPDATE: As per Stuart Popejoy's comment, this sort of abstraction can indeed be achieved using modrefs. Here is an example of a module that implements a generic method over any module implementing a certain interface:
(interface iface
(defun op:integer (arg:string)))
(module impl1 G
(defcap G () true)
(implements iface)
(defun op:integer (arg:string) (length arg)))
(module impl2 G
(defcap G () true)
(implements iface)
(defun op:integer (arg:string) -1))
(module app G
(defcap G () true)
(defun go:integer (m:module{iface} arg:string)
(m::op arg)))
(expect "impl1" 5 (app.go impl1 "hello"))
(expect "impl2" -1 (app.go impl2 "hello"))

"Failure: require-capability: not granted" How do I grant a capability to my module?

I've got a very simple function (increase-count), and I do not want this to be callable by anybody except code in the module. For this, I am using (require-capability (PRIVATE)). As expected, I get the following error.
Error from (api.testnet.chainweb.com): : Failure: require-capability: not granted: (free.guard-test-01.PRIVATE)
How do I grant my module the PRIVATE capability?
(defcap PRIVATE ()
true
)
(defun increase-count (key:string)
;increase the count of a key in a table by 1
(require-capability (PRIVATE))
(update counts-table key {"count": (+ 1 (get-count key))})
)
surround the call increase-count like this:
(with-capability (PRIVATE) (increase-count "abc"))
more in general:
(with-capability (CAP) expr) will evaluate CAP to see whether you can grant it (this is the place where acquisition can fail), and then expr will be evaluated with CAP in scope if you successfully acquire it.
(require-capability (CAP)) is then what you use within the scope of the functions you're trying to enforce CAP is present before you can proceed

Limit Array to multiple specific data types

I am working on refactoring a tool to OOP in PS5.
I have a number of classes. Sets can contain other Sets as well as Packages. Packages can contain other Packages and Tasks. And Tasks can contain other Tasks. For example...
Set1
Package1.1
Task1.1
Set2
Package2.1
Task2.1
Set2A
Package2A
Task2A.1
Task2A.2
Package2.2
Task2.2
Set3
Package3.1
Task3.1
Task3.1A
I plan to have Set, Package and Task classes, but there are a number of different Tasks with some common features and some unique, so I will have a base Task class that is then extended by the various final task classes.
My question relates to the data structure to contain the nested objects. If each class could only contain the next deeper type everything would be easy; the variable to hold the Packages in a Set could be an array of Packages, i.e. [Package[]]$Contents.
I could make it super flexible and just do an array; [Array]$Contents, but that allows for invalid items like strings and such.
Alternatively I could have some sort of Root class, with Sets, Packages and Tasks all extended that, and final Tasks then extending Tasks, and use[Root[]]$Contents or some such. But that might not be possible and it would still allow for adding a Task to a Set, since a final Task class would ultimately be extending from Root.
So, the question becomes, can you define an array that accepts multiple possible types but is still limited, something like [Set/Package[]]$Contents? Or is there perhaps a totally different way to define a variable that limits the valid members? An Enum seems to have potential, but it seems like they are limited to strings as I tried
enum AllowedTypes {
[Array]
[Strings]
}
and that in no good.
Or am I best of just using an Array and validating what I am adding in the Add method of each Class? I can see a possible solution there where I have overloaded Add methods in the Set class, one that takes a Set, one that takes a Package, and one that takes a generic object and throws an error to log. Assuming that the more specific overload method takes priority rather than everything going to the generic method since it's technically valid. Or perhaps that generic method won't even work since the collection of overloaded Add methods technically can't collapse to one valid choice because a Set is both a [Set] and a [PSObject] I guess.
PetSerAl, as countless times before, has provided an excellent (uncommented) solution in a comment on the question, without coming back to post that solution as an answer.
Given the limits of code formatting in comments, it's worth presenting the solution in a more readable format; additionally, it has been streamlined, modularized, extended, and commented:
In short: a PowerShell custom class (PSv5+) is used to subclass standard type [System.Collections.ObjectModel.Collection[object]] in order to limit adding elements to a list of permitted types passed to the constructor.
class MyCollection : System.Collections.ObjectModel.Collection[object] {
# The types an instance of this collection
# is permitted to store instance of, initialized via the constructor.
[Type[]] $permittedTypes
# The only constructor, to which the permitted types must be passed.
MyCollection([Type[]] $permittedTypes) { $this.permittedTypes = $permittedTypes }
# Helper method to determine if a given object is of a permitted type.
[bool] IsOfPermittedType([object] $item) {
return $this.permittedTypes.Where({ $item -is $_ }, 'First')
}
# Hidden helper method for ensuring that an item about to be inserted / added
# / set is of a permissible type; throws an exception, if not.
hidden AssertIsOfPermittedType([object] $item) {
if (-not $this.IsOfPermittedType($item)) {
Throw "Type not permitted: $($item.GetType().FullName)"
}
}
# Override the base class' .InsertItem() method to add type checking.
# Since the original method is protected, we mark it as hidden.
# Note that the .Add() and .Insert() methods don't need overriding, because they
# are implemented via this method.
hidden InsertItem([int] $index, [object] $item) {
$this.AssertIsOfPermittedType($item)
([System.Collections.ObjectModel.Collection[object]] $this).InsertItem($index, $item)
}
# Override the base class' SetItem() method to add type checking.
# Since the original method is protected, we mark it as hidden.
# This method is implicitly called when indexing ([...]) is used.
hidden SetItem([int] $index, [object] $item) {
$this.AssertIsOfPermittedType($item)
([System.Collections.ObjectModel.Collection[object]] $this).SetItem($index, $item)
}
# Note: Since the *removal* methods (.Remove(), .RemoveAt())
# need to type checking, there is no need to override them.
}
With the above class defined, here's sample code that exercises it:
# Create an instance of the custom collection type, passing integers and strings
# as the only permitted types.
# Note the (...) around the type arguments, because they must be passed
# as a *single argument* that is an *array*.
# Without the inner (...) PowerShell would try to pass them as *individual arguments*.
$myColl = [MyCollection]::new(([int], [string]))
# OK, add an [int]
# .Add() implicitly calls the overridden .InsertItem() method.
$myColl.Add(1)
$myColl.Add('hi') # OK, add a [string]
# OK, override the 1st element with a different [int]
# (though a [string] would work too).
# This implicitly calls the overridden .SetItem() method.
$myColl[0] = 2
# OK - insert a [string] item at index 0
$myColl.Insert(0, 'first')
# $myColl now contains: 'first', 2, 'hi'
# Try to add an impermissible type:
$myColl.Add([long] 42)
# -> Statement-terminating error:
# 'Exception calling "Add" with "1" argument(s): "Type not permitted: System.Int64"'

Eiffel: Is there a way to test a given Generic parameter of a Class without any attached instance of it?

Is there a way to test a given Generic parameter of a Class without any attached instance of it?
class BAG[G -> MOUSE]
feature --
discriminate
do
if G.conforms_to (MAMMAL) then
io.putstring ("you gave me a real animal")
elseif G.conforms_to (COMPUTER_ACCESSORY) then
io.putstring ("Seems you don't like animals such as computers")
else
io.pustring ("Still dont know what you are dealing with")
end
end
You've almost nailed it. The missing part is curly braces and parentheses:
if ({G}).conforms_to ({MAMMAL}) then
io.put_string ("You gave me a real animal.")
elseif ({G}).conforms_to ({COMPUTER_ACCESSORY}) then
io.put_string ("Seems you don't like animals such as computers.")
else
io.put_string ("Still don't know what you are dealing with.")
end
Explanation:
{FOO}, where FOO is a type name, stands for a type object. It works for any type, including formal generics, thus {G} and {MAMMAL}.
The syntax {FOO}.bar is reserved for non-object calls. But here we want an object call on the type object. Therefore, {G} is enclosed in parentheses: ({G}).conforms_to (instead of {G}.conforms_to).

Flink Scala API functions on generic parameters

It's a follow up question on Flink Scala API "not enough arguments".
I'd like to be able to pass Flink's DataSets around and do something with it, but the parameters to the dataset are generic.
Here's the problem I have now:
import org.apache.flink.api.scala.ExecutionEnvironment
import org.apache.flink.api.scala._
import scala.reflect.ClassTag
object TestFlink {
def main(args: Array[String]) {
val env = ExecutionEnvironment.getExecutionEnvironment
val text = env.fromElements(
"Who's there?",
"I think I hear them. Stand, ho! Who's there?")
val split = text.flatMap { _.toLowerCase.split("\\W+") filter { _.nonEmpty } }
id(split).print()
env.execute()
}
def id[K: ClassTag](ds: DataSet[K]): DataSet[K] = ds.map(r => r)
}
I have this error for ds.map(r => r):
Multiple markers at this line
- not enough arguments for method map: (implicit evidence$256: org.apache.flink.api.common.typeinfo.TypeInformation[K], implicit
evidence$257: scala.reflect.ClassTag[K])org.apache.flink.api.scala.DataSet[K]. Unspecified value parameters evidence$256, evidence$257.
- not enough arguments for method map: (implicit evidence$4: org.apache.flink.api.common.typeinfo.TypeInformation[K], implicit evidence
$5: scala.reflect.ClassTag[K])org.apache.flink.api.scala.DataSet[K]. Unspecified value parameters evidence$4, evidence$5.
- could not find implicit value for evidence parameter of type org.apache.flink.api.common.typeinfo.TypeInformation[K]
Of course, the id function here is just an example, and I'd like to be able to do something more complex with it.
How it can be solved?
you also need to have TypeInformation as a context bound on the K parameter, so:
def id[K: ClassTag: TypeInformation](ds: DataSet[K]): DataSet[K] = ds.map(r => r)
The reason is, that Flink analyses the types that you use in your program and creates a TypeInformation instance for each type you use. If you want to create generic operations then you need to make sure a TypeInformation of that type is available by adding a context bound. This way, the Scala compiler will make sure an instance is available at the call site of the generic function.

Resources