How do I serialize None in F#? The following code throws an System.ArgumentNullException: Object Graph cannot be null. error:
let f = System.Runtime.Serialization.Formatters.Binary.BinaryFormatter()
let m = System.IO.MemoryStream()
f.Serialize (m, None)
For some performance reasons, the compiler often will make None = null. I think the best solution is then to wrap the whole thing in an extra layer of Option
like this
let f = System.Runtime.Serialization.Formatters.Binary.BinaryFormatter()
let m = System.IO.MemoryStream()
f.Serialize (m,Some( None))
Then you just remove that extra Some when you deserialize
Try using a different serializer, like NetDataContractSerializer. From what I know BinaryFormatter is being considered as legacy and has a few other issues too, for instance this.
Related
I just started my first F# project and coming from the JVM world, I really like Kotlin's nullability syntax and was wondering how I could achieve similarily compact syntax in F#.
Here's an example:
class MyClass {
fun doSomething() {
// ...
}
}
// At some other place in the code:
val myNullableValue: MyClass? = null
myNullableVallue?.doSomething()
What this does:
If myNullableValue is not null, i.e. there is some data, doSomething() is called on that object.
If myNullableValue is null (like in the code above), nothing happens.
As far as I see, the F# equivalent would be:
type MyClass =
member this.doSomething() = ()
type CallingCode() =
let callingCode() =
let myOptionalValue: MyClass option = None
match myOptionalValue with
|Some(x) -> x.doSomething()
|None -> ()
A stamement that is 1 line long in Kotlin is 3 lines long in F#. My question is therefore whether there's a shorter syntax that acomplishes the same thing.
There is no built-in operator for doing this in F# at the moment. I suspect that the reason is that working with undefined values is just less frequent in F#. For example, you would never define a variable, initialize it to null and then have some code that may or may not set it to a value in F#, so the usual way of writing F# eliminates many of the needs for such operator.
You still need to do this sometimes, for example when using option to represent something that can legitimately be missing, but I think this is less frequent than in other languages. You also may need something like this when interacting with .NET, but then it's probably good practice to handle nulls first, before doing anything else.
Aside from pattern matching, you can use Option.map or an F# computation expression (there is no standard one, but it's easy to use a library or define one - see for example). Then you can write:
let myOptionalValue: MyClass option = None
// Option #1: Using the `opt` computation expression
opt { let! v = myOptionalValue
return v.doSomething() }
// Option #2: Using the `Option.map` function
myOptionalValue |> Option.map (fun v -> v.doSomething() )
For reference, my definition of opt is:
type OptionBuilder() =
member x.Bind(v,f) = Option.bind f v
member x.Return v = Some v
member x.ReturnFrom o = o
member x.Zero () = None
let opt = OptionBuilder()
The ?. operator has been suggested to be added to F#.
https://github.com/fsharp/fslang-suggestions/issues/14
Some day it will be added, I hope soon.
I am trying to list out the columns of each table in an MSSQL database. I can get them fine, but I need to turn them into generic types for use elsewhere. (Python types would be more ideal but not sure how to do that?)
My code so far works until I come across a BIT type column.
from sqlalchemy import *
from sqlalchemy.engine import URL
connection_string = f"DRIVER={{ODBC Driver 17 for SQL Server}};SERVER={auth['server']};DATABASE={auth['database']};UID={auth['username']};PWD={auth['password']}"
connection_url = URL.create("mssql+pyodbc", query={"odbc_connect": connection_string})
engine = create_engine(connection_url)
metadata = MetaData(schema="Audit")
metadata.reflect(bind=engine)
for table in metadata.sorted_tables:
print('\n' + table.name)
for col in table.columns:
name = col.name
type = col.type.as_generic()
print(name, type)
I get the error:
NotImplementedError: Default TypeEngine.as_generic() heuristic method was unsuccessful for sqlalchemy.dialects.mssql.base.BIT. A custom as_generic() method must be implemented for this type class.
I have tried a number of things to work around this, but I'd like to learn what I need to do to fix it properly.
Can I make a custom method that turns BIT to INTEGER? And if so how can I implement it?
Thanks,
Solved. Was a bug, see comments on first post.
I have just downloaded the last version of ILNumerics, to be used in my F# project. Is it possible to leverage on this library in F#? I have tried simple computations and it seems very cumbersome (in F#).
I would like to set up a constrained (or even unconstrained) optimization problem. The usual Rosenbrock function would do and then I will use my own function. I am having hard times in having even an Array being defined. The only kind of array I could define was a RetArray, for example with this code
let vector = ILMath.vector<float>(1.0, 2.0)
The compiler signals that vector is a RetArray; I think this is due to the fact that it is returning from a function (i.e.: ILMath.vector). If I define another similar vector, I can -e.g.- sum vectors, simply writing, for example
let a = ILMath.vector<float>(1.0, 2.0)
let b = ILMath.vector<float>(3.2,2.2)
let c = a + b
and I get
RetArray<float> = seq [4.2; 4.2]
but if I try to retrieve the value of c, again, writing, for example in FSI,
c;;
I get
Error: Object reference not set to an instance of an object.
What is the suggested way of using ILNumerics in F#? Is it possible to use the library natively in F# or I am forced to call my F# code from a C# library to use the whole ILNumerics library? Other than with the problem cited, I have problems in understanding the very basic logic of ILNumerics, when ported in F#.
For example, what would be the F# equivalent of the C# using scope as in the example code, as in:
using (ILScope.Enter(inData)) { ...
}
Just to elaborate a bit on brianberns' answer, there are a couple of things you could do to make it easier for yourself.
I would personally not go the route of defining a custom operator - especially one that overrides an existing one. Instead, perhaps you should consider using a computation expression to work with the ILMath types. This will allow you to hide a lot of the uglyness, that comes when working with libraries making use of non-F# standards (e.g. implicit type conversions).
I don't have access to ILMath, so I have just implemented these dummy alternatives, in order to get my code to compile. I suspect you should be able to just not copy that in, and the rest of the code will work as intended
module ILMath =
type RetArray<'t> = { Values: 't seq }
and Array<'t> = { OtherValues: 't seq } with
static member op_Implicit(x: RetArray<_>) = { OtherValues = x.Values }
static member inline (+) (x1, x2) = { Values = (x1.OtherValues, x2.OtherValues) ||> Seq.map2 (+) }
type ILMath =
static member vector<'t>([<ParamArray>] vs : 't []) = { ILMath.Values = vs }
If you have never seen or implemented a computation expression before, you should check the documentation I referenced. Basically, it adds some nice, syntactic sugar on top of some uglyness, in a way that you decide. My sample implementation adds just the let! (desugars to Bind) and return (desugars to Return, duh) key words.
type ILMathBuilder() =
member __.Bind(x: ILMath.RetArray<'t>, f) =
f(ILMath.Array<'t>.op_Implicit(x))
member __.Return(x: ILMath.RetArray<'t>) =
ILMath.Array<'t>.op_Implicit(x)
let ilmath = ILMathBuilder()
This should be defined and instantiated (the ilmath variable) at the top level. This allows you to write
let c = ilmath {
let! a = vector(1.0, 2.0)
let! b = vector(3.2, 2.2)
return a + b
}
Of course, this implementation adds only support for very few things, and requires, for instance, that a value of type RetArray<'t> is always returned. Extending the ILMathBuilder type according to the documentation is the way to go from here.
The reason that the second access of c fails is that ILNumerics is doing some very unusual memory management, which automatically releases the vector's memory when you might not expect it. In C#, this is managed via implicit conversion from vector to Array:
// C#
var A = vector<int>(1, 2, 3); // bad!
Array<int> A = vector<int>(1, 2, 3); // good
F# doesn't have implicit type conversions, but you can invoke the op_Implicit member manually, like this:
open ILNumerics
open type ILMath // open static class - new feature in F# 5
let inline (!) (x : RetArray<'t>) =
Array<'t>.op_Implicit(x)
[<EntryPoint>]
let main argv =
let a = !vector<float>(1.0, 2.0)
let b = !vector<float>(3.2,2.2)
let c = !(a + b)
printfn "%A" c
printfn "%A" c
0
Note that I've created an inline helper function called ! to make this easier. Every time you create an ILNumerics vector in F#, you must call this function to convert it to an array. (It's ugly, I know, but I don't see an easier alternative.)
To answer your last question, the equivalent F# code is:
use _scope = Scope.Enter(inData)
...
I'm trying to figure out native interface. I'm trying to send some message using UDP. Here what I have:
module UDPTest where
data StringAsBytes = native java.lang.String where
native getBytes :: String -> ST s (Mutable s (JArray Byte))
data InetSocketAddress = native java.net.InetSocketAddress where
native new :: String -> Int -> ST s (Mutable s InetSocketAddress)
data DatagramPacket = native java.net.DatagramPacket where
native new :: Mutable s (JArray Byte) -> Int -> Mutable s InetSocketAddress -> ST s (Mutable s DatagramPacket)
data DatagramSocket = native java.net.DatagramSocket where
native new :: () -> IOMutable DatagramSocket throws SocketException
native send :: Mutable RealWorld DatagramSocket -> MutableIO DatagramPacket -> IO () throws IOException
native close :: MutableIO DatagramSocket -> IO ()
data SocketException = native java.net.SocketException
derive Exceptional SocketException
main _ = do
messageStr = "hello world;\n"
messageAsBytes <- StringAsBytes.getBytes messageStr
address <- InetSocketAddress.new "localhost" 3003
messageLen <- messageAsBytes.getLength
packet <- DatagramPacket.new messageAsBytes messageLen address
socket <- DatagramSocket.new ()
socket.send packet
socket.close
This code accidentally runs but it makes me wonder few things. Firstly, what should be a type of DatagramSocket.new to reflect the fact of throwing exception? I had tried to pack it into Maybe but it ended up in a total mess. Is there any way to do it? For now, I have no idea how to handle exceptions in main and this doesn't address it fully or maybe I'm missing something.
Secondly, Why I was forced by compiler to change InetSocketAddress from pure to impure, to use it in DatagramSocket.new? I was also forced to use mutable version of JArray wherever it was needed in code.
Concerning exceptions: There are 2 ways of managing exceptions.
The first is by wrapping the return type in an Either. This will give you the value you want in Right and the exception in Left when it occures.
To handle the exception, you generally use pattern matching or the either function. Unfortunately, in IO code (like in your case) this would lead to code like
do
r1 <- Socket.new ...
case r1 of
Left -> -- handle exception
Right x -> do
r2 -> x.send ....
case r2 of
....
which is not so nice. Therefore, the Either style is preferred for pure functions, and for IO/ST actions the other style is preferred.
For this, declare your native functions with a throws ... clause, as you have done already for send and new. The exception aware IO/ST action then looks like:
foo = do
s <- Socket.new
d <- s.send ....
...
`catch` (\x1::SocketException -> ...)
`catch` (\x2::IOException -> ....)
....
`finally` finallyaction
There may be as many catches as you need, but make sure to order them so that the most specific one comes before the less specific one, i.e. if ExceptionDerive extends ExceptionSuper, then the catch for ExceptionDerived must occur before the other one.
The finally clause is optional. Note that you don't have access to variables bound in the do block neither in the catch clauses nor in the finally clause. If you need this, you need to do the exception handling on a lower level (i.e., where some variable is bound to the value you need).
Please look up catch and finally in the frege doc or on Froogle.
Make sure the catch is indented less than the code in the do it guards. This is to make sure the compiler sees:
do { .... } `catch` handler
You can as well write code without caring about exceptions, and add them only later. For example, you start with:
action1 a b c = do
dothis a
dothat b
dosomethingelse c
pure whatyouwant
Later, you can rename action1 to action1noex and write
action1 a b c = action1noex a b c
`catch` ....
Second point. For data types that can only be used in the IO Monad, it is recommended to declare them as
data Socket = mutable native java......
This makes it possible to simply write Socket instead of Mutable s Socket or Mutable RealWorld Socket, since the compiler knows that such a value will always be mutable. You can use such types only in native functions that have a IO result.
Conversely, for data types that you just construct but never use in an impure way, you can define them as pure native.
I'm not sure about InetSockAddress but I guess it is not modified once constructed?
Likewise, rgd. the byte array. If you always and only ever want to convert this from and to strings, it can be treated as an utf8 text type (which we unfortunately don't have yet in the library). This would look like
data Charset = pure native java.nio.charset.Charset
pure native utf8 "java.nio.charset.StandardCharsets.UTF_8" :: Charset
data Bytes = pure native "byte[]"
pure native getBytes :: String -> Charset -> Bytes
pure native getString new :: Bytes -> Charset -> String
toBytes s = getBytes s utf8
fromBytes bs = getString bs utf8
(untested, please ignore the warning concerning byte[] for now)
Firstly: you can wrap result of function (method) throwing exception into Either, like this: native fn :: A -> Either SomeException B or sugared version: native fn :: (SomeException | B).
Secondly: Frege values are immutable. If you have got some data type A defined in Frege it is immutable. You are allowed to wrap some Java types and for immutable you mark them pure: data D = pure native com.acme.D. InetSocketAddress is not declared pure. This means that ImmutableSocketAddress can be changed by some other thread anywhere in time(for example closing socket). So Frege compiler marks it as Mutable. You can pass such data to Java functions only wrapped with Mutable taint.
You can write a function in Frege that doesn't need Mutable taint, but to pass it an argument you need to use some readonly or Freezable to get rid of Mutable.
I'm fairly new to Kryo so forgive me if I've made a silly mistake.... I have read the manual, and I think I understand generally how Kryo serializes, but I'm having trouble deserializing a JComboBox.
First, I tried this:
Kryo kryo = new Kryo();
Output output = new Output(new FileOutputStream("/tempTest/newTest.kr"));
JComboBox objectToWrite = new JComboBox();
kryo.writeObject(output, objectToWrite);
output.flush();
output.close();
then read...
Input input = new Input(new FileInputStream("/tempTest/newTest.kr"));
JComboBox cbox = kryo.readObject(input, JComboBox.class);
Doing this generates a "missing no-arg constructor" exception. So I set the fallback instantiator strategy:
((DefaultInstantiatorStrategy) kryo.getInstantiatorStrategy()).setFallbackInstantiatorStrategy(new StdInstantiatorStrategy());
However, now I get this exception:
Exception in thread "main" java.lang.IllegalAccessError: tried to access method javax.swing.plaf.metal.MetalComboBoxButton.<init>()V from class javax.swing.plaf.metal.MetalComboBoxButtonConstructorAccess
at javax.swing.plaf.metal.MetalComboBoxButtonConstructorAccess.newInstance(Unknown Source)
at com.esotericsoftware.kryo.Kryo$DefaultInstantiatorStrategy$1.newInstance(Kryo.java:1193)
at com.esotericsoftware.kryo.Kryo.newInstance(Kryo.java:1061)
at com.esotericsoftware.kryo.serializers.FieldSerializer.create(FieldSerializer.java:547)
at com.esotericsoftware.kryo.serializers.FieldSerializer.read(FieldSerializer.java:523)
at com.esotericsoftware.kryo.Kryo.readClassAndObject(Kryo.java:761)
at com.esotericsoftware.kryo.serializers.CollectionSerializer.read(CollectionSerializer.java:116)
at com.esotericsoftware.kryo.serializers.CollectionSerializer.read(CollectionSerializer.java:22)
at com.esotericsoftware.kryo.Kryo.readObject(Kryo.java:679)
at com.esotericsoftware.kryo.serializers.ObjectField.read(ObjectField.java:106)
at com.esotericsoftware.kryo.serializers.FieldSerializer.read(FieldSerializer.java:528)
at com.esotericsoftware.kryo.Kryo.readObject(Kryo.java:657)
at T2SaveLoad.saveLoad(T2SaveLoad.java:112)
at T2SaveLoad.main(T2SaveLoad.java:40)
I'm not sure exactly what is happening, can anyone help?
Also, how is the instantiation strategy chosen by kryo? Does each serializer have a different instantiator strategy, or does kryo just have a default and a fallback for all objects it deserializes?
What if you do:
kryo.register(JComboBox.class, new JavaSerializer());
(which does in fact serialize/deserialize without any errors) - native java deserialization doesn't call the constructor (apart from the no-arg one in the first superclass that doesn't implement serializable), but if you haven't told kryo to set the instantiator strategy to StdInstantiatorStrategy(), does it still try to use a constructor? or does the fact that it is using its JavaSerializer make it use some other instantiation strategy? (which would perhaps make the instantiation strategy serializer-specific?
I hope this makes sense, please let me know if it doesn't!!