Module inside an object - ocaml

I would like to define a parameterized module inside an object by the type of this object.
I have two module interlocked :
(* Parameters*)
module type A = sig
type agent
type intern_agent = { i : agent}
val create : agent -> intern_agent
end
module type E = sig
type event
end
module type StateType = sig
type agent
type event
type state_t = {
mutable name : string;
mutable parentstate : state_t option;
}
end
module State (A : A) (E : E) = struct
type agent = A.agent
type event = E.event
type state_t = {
mutable name : string;
mutable parentstate : state_t option;
}
(*...*)
end
module Agent (S : StateType) =
struct
type agent = S.agent
type event = S.event
type state_t = S.state_t
type agent_t = {
mutable agent : agent ;
}
let create a1 = {
agent = a1;
}
end
(* An implementation of E*)
type event1 = Event1 | Event2;;
module E = struct type event = event1 end;;
What I would like to do is something like that (which is syntacticly incorrect but represents what I would like to do) :
class character = object (self :'self)
val mutable position = (0,0)
val agent =
let A = (module Ag = struct
type agent = 'self
type intern_agent = { i : agent}
let create a = { i = a }
end)
in
let Ag = (module Agent(State(A)(E)) ) in
Ag.create self
method getPosition = position
end;;
How can I write this to be able to define a value which is an Agent parametrized by itself ?
Thank you

Syntactically correct version of a character class definition is
class character = object (self :'self)
val mutable position = (0,0)
val agent =
let module A = struct
type agent = character
type intern_agent = { i : agent}
let create a = { i = a }
end in
let module Ag = Agent(State(A)(E)) in
Ag.create self
method getPosition = position
end
Although, it wont compile, since agent_t will escape the scope of the value agent definition. Indeed, you're asking a compiler to allow you to return a value from a function that has type local to the function.
I wish I can give you some advice on how to redesign your code, but I need more information about your intentions.

Related

pass type to module for abstract data type

I am trying to create a heap module (and eventually priority queue) implemented with an array.
The portion of the heap I have written so far compiles fine:
module MinHeap = {
type elem
type heap = array<elem>
let make = (): heap => []
let insert = (h: heap, e: elem): heap => {
Belt.Array.push(h, e)->ignore
h
}
let next = (h: heap): option<elem> => Belt.Array.get(h, 0)
}
However I cannot instantiate it:
let h = MinHeap.make()
MinHeap.insert(h, 10)->ignore
The build fails with
FAILED: src/use-case-composites/heap-LogicParser.cmj
We've found a bug for you! /Users//projects//src/use-case-composites/heap.res:25:19-20
23 │
24 │ let h = MinHeap.make()
25 │ MinHeap.insert(h, 10)->ignore
26 │
This has type: int
Somewhere wanted: MinHeap.elem
There must be a away to pass types into modules. For example I am able to type option, but how do you do that in a custom module?
If you don't need any behaviour associated with the elem type, you could simply parameterize heap over it, the same way array is:
module MinHeap = {
type heap<'elem> = array<'elem>
let make = (): heap<_> => []
let insert = (h: heap<'elem>, e: 'elem): heap<'elem> => {
Belt.Array.push(h, e)->ignore
h
}
let next = (h: heap<'elem>): option<'elem> => Belt.Array.get(h, 0)
}
Edit: To also answer your question of how to "pass a type into a module", you could do this using a functor:
module type Config = {
type elem
}
module MinHeap = (Config: Config) => {
type elem = Config.elem
type heap = array<elem>
let make = (): heap => []
let insert = (h: heap, e: elem): heap => {
Belt.Array.push(h, e)->ignore
h
}
let next = (h: heap): option<elem> => Belt.Array.get(h, 0)
}
module IntMinHeap = MinHeap({
type elem = int
})
let h = IntMinHeap.make()
IntMinHeap.insert(h, 10)->ignore
It seems a bit overkill for this use case though.

Corda - SignTransactionFlow and sendAndReceive

I have two parties (A and B).
A sends to B a Corda State using SignTransactionFlow, so also obtains the counterparty signature for that transaction.
Is it possibile to share a Corda State without using a SignTransactionFlow but using a sendAndReceive calls?
If so, will the counterparty receiving a Corda State through sendAndReceive be able to consume that state?
Yes, it's possible to send states using send() and receive(). Here is a code sample that I tested to see if it works:
class TestContract : Contract{
companion object{
#JvmStatic
val ID = "package net.corda.sample.TestContract"
}
override fun verify(tx: LedgerTransaction) {
}
}
#BelongsToContract(TestContract::class)
class TestState(val owner : Party, val value : String) : ContractState {
override val participants: List<AbstractParty>
get() = listOf(owner)
}
#InitiatingFlow
#StartableByRPC
class receiveStateFlow(private val counterparty: Party) : FlowLogic<Unit>() {
override val progressTracker = ProgressTracker()
val log = loggerFor<receiveStateFlow>()
#Suspendable
override fun call() {
val counterpartySession = initiateFlow(counterparty)
val counterpartyData = counterpartySession.sendAndReceive<TestState>("hello")
counterpartyData.unwrap { msg ->
log.warn(msg.value)
assert((msg.participants.first()) == counterparty)
}
}
}
#InitiatedBy(receiveStateFlow::class)
class sendStateFlow(private val counterpartySession: FlowSession) : FlowLogic<Unit>() {
#Suspendable
override fun call() {
val counterpartyData = counterpartySession.receive<String>()
counterpartyData.unwrap { msg ->
assert(msg == "hello")
}
val newState = TestState(serviceHub.myInfo.legalIdentities.first(), "someValue")
counterpartySession.send(newState)
}
}
However, this method will not consume any states. This can only happen if you use those states as the output of a Transaction. Hence, the Party that receives the states should use those exact states as a output in a TransactionBuilder in the same Flow and go on with signing and finalising the transaction.

Testing Spring cloud stream with kafka stream binder: using TopologyTestDriver I get the error of "The class is not in the trusted packages"

I have this simple stream processor (not a consumer/producer) using kafka streams binder.
#Bean
fun processFoo():Function<KStream<FooName, FooAddress>, KStream<FooName, FooAddressPlus>> {
return Function { input-> input.map { key, value ->
println("\nPAYLOAD KEY: ${key.name}\n");
println("\nPAYLOAD value: ${value.address}\n");
val output = FooAddressPlus()
output.address = value.address
output.name = value.name
output.plus = "$value.name-$value.address"
KeyValue(key, output)
}}
}
I'm trying to test it using the TopologyTestDriver:
#SpringBootTest(
webEnvironment = SpringBootTest.WebEnvironment.NONE,
classes = [Application::class, FooProcessor::class]
)
class FooProcessorTests {
var testDriver: TopologyTestDriver? = null
val INPUT_TOPIC = "input"
val OUTPUT_TOPIC = "output"
val inputKeySerde: Serde<FooName> = JsonSerde<FooName>()
val inputValueSerde: Serde<FooAddress> = JsonSerde<FooAddress>()
val outputKeySerde: Serde<FooName> = JsonSerde<FooName>()
val outputValueSerde: Serde<FooAddressPlus> = JsonSerde<FooAddressPlus>()
fun getStreamsConfiguration(): Properties? {
val streamsConfiguration = Properties()
streamsConfiguration[StreamsConfig.APPLICATION_ID_CONFIG] = "TopologyTestDriver"
streamsConfiguration[StreamsConfig.BOOTSTRAP_SERVERS_CONFIG] = "dummy:1234"
streamsConfiguration[JsonDeserializer.TRUSTED_PACKAGES] = "*"
streamsConfiguration["spring.kafka.consumer.properties.spring.json.trusted.packages"] = "*"
return streamsConfiguration
}
#Before
fun setup() {
val builder = StreamsBuilder()
val input: KStream<FooName, FooAddress> = builder.stream(INPUT_TOPIC, Consumed.with(inputKeySerde, inputValueSerde))
val processor = FooProcessor()
val output: KStream<FooName, FooAddressPlus> = processor.processFoo().apply(input)
output.to(OUTPUT_TOPIC, Produced.with(outputKeySerde, outputValueSerde))
testDriver = TopologyTestDriver(builder.build(), getStreamsConfiguration())
}
#After
fun tearDown() {
try {
testDriver!!.close()
} catch (e: RuntimeException) {
// https://issues.apache.org/jira/browse/KAFKA-6647 causes exception when executed in Windows, ignoring it
// Logged stacktrace cannot be avoided
println("Ignoring exception, test failing in Windows due this exception:" + e.localizedMessage)
}
}
#org.junit.Test
fun testOne() {
val inputTopic: TestInputTopic<FooName, FooAddress> =
testDriver!!.createInputTopic(INPUT_TOPIC, inputKeySerde.serializer(), inputValueSerde.serializer())
val key = FooName()
key.name = "sherlock"
val value = FooAddress()
value.name = "sherlock"
value.address = "Baker street"
inputTopic.pipeInput(key, value)
val outputTopic: TestOutputTopic<FooName, FooAddressPlus> =
testDriver!!.createOutputTopic(OUTPUT_TOPIC, outputKeySerde.deserializer(), outputValueSerde.deserializer())
val message = outputTopic.readValue()
assertThat(message.name).isEqualTo(key.name)
assertThat(message.address).isEqualTo(value.address)
}
}
When running it, I get this error in line inputTopic.pipeInput(key, value)
The class 'package.FooAddress' is not in the trusted packages: [java.util, java.lang]. If you believe this class is safe to deserialize, please provide its name. If the serialization is only done by a trusted source, you can also enable trust all ().*
Any ideas on how to solve this? Setting those properties in getStreamsConfiguration() is not helping. Please note that this is a stream processor, not a consumer/producer.
Thanks a lot!
When Kafka creates the Serde itself, it applies the properties by calling configure().
Since you are instantiating the Serde yourself, you need to call configure() on it passing in the map of properties.
That's how the trusted packages property gets propagated to the deserializer.
Or, you can call setTrustedPackages() on the deserializer.
So, for completeness, here's how the code looks when configuring the serde as #GaryRussell suggests:
private fun getStreamsConfiguration(): Properties? {
// Don't set the trusted packages here since topology test driver does not know about Spring
val streamsConfiguration = Properties()
streamsConfiguration[StreamsConfig.APPLICATION_ID_CONFIG] = "TopologyTestDriver"
streamsConfiguration[StreamsConfig.BOOTSTRAP_SERVERS_CONFIG] = "dummy:1234"
}
#Before
fun setup() {
val builder = StreamsBuilder()
// Set the trusted packages for all serdes
val config = mapOf<String, String>(JsonDeserializer.TRUSTED_PACKAGES to "*")
inputKeySerde.configure(config, true)
inputValueSerde.configure(config, false)
outputKeySerde.configure(config, true)
outputValueSerde.configure(config, false)
}
And the rest of the code remains as described in the question. All credit to #GaryRusell.

how to mock/match lambda in kotlin method signature

I have some code on the follwing form:
#Language("SQL")
val someSql = """
SELECT foo
FROM bar
WHERE foo = :foo
"""
return session.select(some, mapOf("foo" to foo)) {
MyObject(
foo = it.string("foo"),
)
}.firstOrNull()
which use the below from com.github.andrewoma.kwery.core. Note the lambda in the method signature:
fun <R> select(#Language("SQL") sql: String,
parameters: Map<String, Any?> = mapOf(),
options: StatementOptions = defaultOptions,
mapper: (Row) -> R): List<R>
I use mockitokotlin2.
I need to return an instance of MyObject when the session select method is called with a select query (containing "SELECT foo").
I was thinking I could pass a mock into the lambda as below (but then it wont match the method call I am trying to mock). The below code is an attempt. But it never matches in eq(function2):
val function2: (Row) -> Int = mock {
onGeneric { invoke(any()) }.thenReturn(MyObject(foo="test-foo"))
}
val session = mock<Session> {
on { select(sql = any(), parameters = any(), options = any(), mapper = eq(function2))}.thenReturn(listOf(MyObject(foo="test-foo")))
}
function2 in my case is not really a mapper, it is not eq to what I am trying to mock, it never matches and the mock is never called.
So what do I put in the mock of session, select instead of eq(function2) in the code above to get MyObject object returned?
I think you just need to specify they type that your mapper is expected to return when setting up the session mock - in your case looks to be Function1<Row, MyObject>
val session = mock<Session> {
on { select(sql = anyString(), parameters = anyMap(), options = any(), mapper = any<Function1<Row, MyObject>>())}.thenReturn(listOf(MyObject(foo="test-foo")))
}

Casting a variable of type 'UnsafeMutableRawPointer' to UnsafeMutablePointer<> in Swift 3

Starting with a class definition as follows:
class Player {
var playbackFile: AudioFileID? = nil
var packetPosition: Int64 = 0
var numPacketsToRead: UInt32 = 0
var packetDescs: UnsafeMutablePointer<AudioStreamPacketDescription>? = nil
var isDone = false
}
Then defining a callback function:
let AQOutputCallback: AudioQueueOutputCallback = {(inUserData, inAQ, inCompleteAQBuffer) -> () in
let aqp = UnsafeMutablePointer<Player>(inUserData).pointee // this gives an error
// more code
}
This results in an error on the second line: "Cannot invoke initializer for type 'UnsafeMutablePointer' with an argument list of type 'UnsafeMutableRawPointer?'
How do I properly cast from type 'UnsafeMutableRawPointer?' to 'UnsafeMutablePointer' in Swift 3?
The following modification eliminated the error:
let aqp = inUserData!.assumingMemoryBound(to: Player.self).pointee
to convert MutableRawPointer to object, we use fromOpaque api
/// Unsafely turns an opaque C pointer into an unmanaged class reference.
///
/// This operation does not change reference counts.
///
/// let str: CFString = Unmanaged.fromOpaque(ptr).takeUnretainedValue()
///
/// - Parameter value: An opaque C pointer.
/// - Returns: An unmanaged class reference to `value`.
public static func fromOpaque(_ value: UnsafeRawPointer) -> Unmanaged<Instance>
example:
var info:UnsafeMutableRawPointer = ....
let obj = Unmanaged<$AnyObject>.fromOpaque(info).takeUnretainedValue()