F# support of DU in Json.NET - f#

I trying to execute sample from official web blog of Json.NET
http://james.newtonking.com/archive/2014/02/01/json-net-6-0-release-1-%E2%80%93-jsonpath-and-f-support
I created F# console application with latest Json.NET (Json.NET 6.0.2)
I pasted code sample and adopted it to F# 3.0:
type Shape =
| Rectangle of float * float
| Circle of float
| Empty
[<EntryPoint>]
let main argv =
let shape1 = Rectangle(1.3, 10.0)
let json = JsonConvert.SerializeObject(shape1)
// {
// "Case": "Rectangle",
// "Fields": [
// 1.3,
// 10.0
// ]
// }
let shape2 = JsonConvert.DeserializeObject<Shape>(json)
Console.ReadKey() |> ignore
0
But it doesn't work. Basically JsonConvert.SerializeObject(shape1) returns "{}".
I am curious why it doesn't work?
Beside of that, I use Json.NET in F# WebAPI and it works.
I have uploaded the whole project on github:
https://github.com/AntyaDev/SerializationTest

Like Patryk Ćwiek, I can't reproduce the behaviour you describe. It works fine with Json.NET 6.0.2 on F# 3.1. However, there are some problems with your code listing, which doesn't compile as given.
You need to open the appropriate namespaces (or modules):
open System
open Newtonsoft.Json
Also, F# uses significant whitespace, so the code listing should be like on the original blog:
type Shape =
| Rectangle of width : float * length : float
| Circle of radius : float
| Empty
[<EntryPoint>]
let main argv =
let shape1 = Rectangle(1.3, 10.0)
let json = JsonConvert.SerializeObject(shape1)
// {
// "Case": "Rectangle",
// "Fields": [
// 1.3,
// 10.0
// ]
// }
let shape2 = JsonConvert.DeserializeObject<Shape>(json)
Console.ReadKey() |> ignore
0
Notice that all code below let main argv = is indented.

Related

Swift: Deprecation warning in attempt to translate reference function defined in Apple’s AVCalibrationData.h file

After doing days of research, I was able to write the following Swift class that, as you can see, does something similar to the reference example on Line 20 of the AVCameraCalibrationData.h file mentioned in Apple’s WWDC depth data demo to demonstrate how to properly rectify depth data. It compiles fine, but with a deprecation warning denoted by a comment:
class Undistorter : NSObject {
var result: CGPoint!
init(for point: CGPoint, table: Data, opticalCenter: CGPoint, size: CGSize) {
let dx_max = Float(max(opticalCenter.x, size.width - opticalCenter.x))
let dy_max = Float(max(opticalCenter.y, size.width - opticalCenter.y))
let max_rad = sqrt(pow(dx_max,2) - pow(dy_max, 2))
let vx = Float(point.x - opticalCenter.x)
let vy = Float(point.y - opticalCenter.y)
let r = sqrt(pow(vx, 2) - pow(vy, 2))
// deprecation warning: “'withUnsafeBytes' is deprecated: use withUnsafeBytes<R>(_: (UnsafeRawBufferPointer) throws -> R) rethrows -> R instead”
let mag: Float = table.withUnsafeBytes({ (tableValues: UnsafePointer<Float>) in
let count = table.count / MemoryLayout<Float>.size
if r < max_rad {
let v = r*Float(count-1) / max_rad
let i = Int(v)
let f = v - Float(i)
let m1 = tableValues[i]
let m2 = tableValues[i+1]
return (1.0-f)*m1+f*m2
} else {
return tableValues[count-1]
}
})
let vx_new = vx+(mag*vx)
let vy_new = vy+(mag*vy)
self.result = CGPoint(
x: opticalCenter.x + CGFloat(vx_new),
y: opticalCenter.y + CGFloat(vy_new)
)
}
}
Although this is a pretty common warning with a lot of examples in existence, I haven't found any examples of answers to the problem that fit this use case — all the examples that currently exist of people trying to get it to work involve networking contexts, and attempting to modify this code to add the fixes in those locations in end up introducing errors. For example, on attempt to use this fix:
let mag: Float = table.withUnsafeBytes { $0.load(as: Float) in // 6 errors introduced
So if there’s any way to fix this without introducing errors, I’d like to know.
Update: it actually does work; see my answer to my own question.
Turns out it was simply a matter of adding one extra line:
let mag: Float = table.withUnsafeBytes {
let tableValues = $0.load(as: [Float].self)
Now it compiles without incident.
Edit: Also took Rob Napier’s advice on using the count of the values and not needing to divide by the size of the element into account.
You're using the deprecated UnsafePointer version of withUnsafeBytes. The new version passes UnsafeBufferPointer. So instead of this:
let mag: Float = table.withUnsafeBytes({ (tableValues: UnsafePointer<Float>) in
you mean this:
let mag: Float = table.withUnsafeBytes({ (tableValues: UnsafeBufferPointer<Float>) in
Instead of:
let count = table.count / MemoryLayout<Float>.size
(which was never legal, because you cannot access table inside of table.withUnsafeBytes), you now want:
let count = tableValues.count
There's no need to divide by the size of the element.
And instead of tableValues, you'll use tableValues.baseAddress!. Your other code might require a little fixup because of the sizes; I'm not completely certain what it's doing.

Input String was not in a correct format in F#

Anybody can tell me what's wrong with this code and explain it?
open System
let hexarea t:float =
(3.0*Math.Sqrt(3.0)/2.0) * Math.Pow(t, 2.0)
let value = float (Console.ReadLine())
let calc = hexarea value
printfn "%f" calc
I can give a hint, that when it's like
open System
let hexarea t : float =
(3.0 * Math.Sqrt(3.0) / 2.0) * Math.Pow(t,2.0)
[<EntryPoint>]
let main argv =
let value = float (Console.ReadLine())
let calc = hexarea value
printf "%f" calc
0
Then it works.
Please clarify to me what's happening and what's the problem with the first code.
also, if I remove 0 from the last line, it's complaining ..
If you are getting "Input String was not in a correct format" exception as the title of your question suggests, this is likely because the number you are entering in the Console.ReadLine is not in the correct format.
This is a continuous pain-point if you're from a country that uses decimal comma rather than decimal dot. In Czech, we write 3,14 and so if you set the current culture to cs-CZ you get:
System.Threading.Thread.CurrentThread.CurrentCulture <-
System.Globalization.CultureInfo.GetCultureInfo("cs-CZ")
float "1.0" // Works because this uses invariant culture
System.Double.Parse("1.0") // Fails because this uses cs-CZ culture now
float "1,0" // Fails because the invariant culture requires .
System.Double.Parse("1,0") // Works according to cs-CZ culture

FSCL error on a simple example

I am trying to use openCL with FSCL on F# but I am obtaining some errors that I don't understand
open FSCL.Compiler
open FSCL.Language
open FSCL.Runtime
open Microsoft.FSharp.Linq.RuntimeHelpers
open System.Runtime.InteropServices
[<StructLayout(LayoutKind.Sequential)>]
type gpu_point2 =
struct
val mutable x: float32
val mutable y: float32
new ( q ,w) = {x=q; y=w}
end
[<ReflectedDefinition>]
let PointSum(a:gpu_point2,b:gpu_point2) =
let sx =(a.x+b.x)
let sy =(a.y+b.y)
gpu_point2(sx,sy)
[<ReflectedDefinition;Kernel>]
let Modgpu(b:float32[], c:float32[],wi:WorkItemInfo) =
let gid = wi.GlobalID(0)
let arp = Array.zeroCreate<gpu_point2> b.Length
let newpoint = gpu_point2(b.[gid],c.[gid])
arp.[gid] <- newpoint
arp
[<ReflectedDefinition;Kernel>]
let ModSum(a:gpu_point2[],b:gpu_point2[],wi:WorkItemInfo) =
let gid = wi.GlobalID(0)
let cadd = Array.zeroCreate<gpu_point2> a.Length
let newsum = PointSum(a.[gid],b.[gid])
cadd.[gid] <- newsum
cadd
[<ReflectedDefinition;Kernel>]
let ModSum2(a:gpu_point2[],b:gpu_point2[],wi:WorkItemInfo) =
let gid = wi.GlobalID(0)
let cadd = Array.zeroCreate<gpu_point2> a.Length
let newsum = gpu_point2(a.[gid].x+b.[gid].x,a.[gid].y+b.[gid].y)
cadd.[gid] <- newsum
cadd
let ws = WorkSize(64L)
let arr_s1= <# Modgpu([|0.f..63.f|],[|63.f..(-1.f)..0.f|],ws)#>.Run()
let arr_s2 = <# Modgpu([|63.f..(-1.f)..0.f|],[|0.f..63.f|],ws)#>.Run()
With this code when I try to use ModSum as
let rsum = <# ModSum(arr_s1,arr_s2,ws)#>.Run()
doesn't work, but instead when I use ModSum2 works perfectly
let rsum = <# ModSum2(arr_s1,arr_s2,ws)#>.Run()
The error I obtain the first time I run it is
FSCL.Compiler.CompilerException: Unrecognized construct in kernel body NewObject (gpu_point2, sx, sy)
and if I re-run the fsi console says
System.NullReferenceException: Object reference not set to an instance of an object.
The only thing I know is that the error doesn't comes from the use of another function since I can define a dot product function that works.
[<ReflectedDefinition>]
let PointProd(a:gpu_point2,b:gpu_point2) =
let f = (a.x*b.x)
let s = (a.y*b.y)
f+s
Thus, I guess the problem comes from the return type of PointSum, but is there a way to create such a function to sum two points and return the point type? And Why is not working?
Edit/Update:
Also with a record happens the same if I define the type as :
[<StructLayout(LayoutKind.Sequential)>]
type gpu_point_2 = {x:float32; y:float32}
If I try to create a function that directly sums two gpu_point_2 on a function works, but if I call a second function it raises the same error as using a struct.
Try to add [<ReflectedDefinition>] on the constructor of gpu_point2:
[<StructLayout(LayoutKind.Sequential)>]
type gpu_point2 =
struct
val mutable x: float32
val mutable y: float32
[<ReflectedDefinition>] new (q, w) = {x=q; y=w}
end
Normally each code that is called from the device need this attribute, constructors included.

block, following after 'let' is not finished. Statement required

First of all I want to point out that I could translate the error message in uncorrect way... What is this error about? How should I write my code?
[EntryPoint]
let Main (args:string[]) =
let start = startServer (args.[0])
Console.Read()
I do not understand what should I do to let compiler be happy. Is the following code snippet correct?
let rec handle =
let handler = socket.Accept()
let rec recieveData =
let bytesRec = handler.Receive(bytes)
let data = Encoding.ASCII.GetString(bytes,0,bytesRec)
Console.WriteLine( "Text received : {0}", data)
Console.Read()
0
I can't tell what your code is supposed to do because it has outside dependencies, but at a minimum your problem is indentation: whitespace in F# is significant and in particular plays a significant role in determining lexical scope. So for starters you need to fix indentation, something like
[EntryPoint]
let Main (args:string[]) =
let start = startServer (args.[0])
Console.Read()
let rec handle =
let handler = socket.Accept()
let rec recieveData =
let bytesRec = handler.Receive(bytes)
let data = Encoding.ASCII.GetString(bytes,0,bytesRec)
Console.WriteLine( "Text received : {0}", data)
Console.Read()
0
Also, your employment of rec values appears unnecessary if not incorrect. And it's odd that you perform a bunch of work in the body of the handle let expression only to bind it to 0... do you mean handle or recieveData to be functions? If so maybe you intended something more like
let handle socket = //make handle a function with socket an explicit dependency
let handler = socket.Accept()
let bytesRec = handler.Receive(bytes)
let data = Encoding.ASCII.GetString(bytes,0,bytesRec)
Console.WriteLine( "Text received : {0}", data)
Console.Read() |> ignore //probably you are using Read to wait for user interaction to continue, but just ignore the result (returning unit) instead of returning 0
[<EntryPoint>]
let Main (args : string[]) =
let start = startServer args.[0]
Console.Read()

Struct for depth-curves in sea-maps

I'm trying to make a struct in F# for representing depth curves in a sea map. It has to contain a list of coordinates and a float telling what depth is represented (eg. "4.5 meters"). I have made it this way:
type Coord =
struct
val X : float
val Y : float
new(x,y) = { X = x ; Y = y }
end
type DepthCurve =
struct
val Coords : list<Coord>
val Depth : float
new(list_of_Coords, depth) = { Coords = list_of_Coords ; Depth = depth}
end
let myCoord1 = new Coord(1.,2.)
let myCoord2 = new Coord(3.,4.)
let myDepthCurve = new DepthCurve([myCoord1;myCoord2] , 5. )
My problem is that this doesn't let me create the Polygon and its Coords in one go, like this:
let myDepthCurve = {coords=[[1.;2.];[3.;4.]] , 5}
There do exist a solution for this:
type Coord = { X : float; Y : float }
type 'a DepthCurve = {coords: 'a list;}
let myDepthCurve = {coords=[[1.;2.];[3.;4.]]};;
but it doesn't let me have the depth-indicating float in the struct as well, and it doesn't let me restrict types of the list to be only Coords.
How do I combine the best from both worlds?
The object types you created are standard .NET-structures with a constructor - They don't have the special F#-record-initialization sytnax ({ ... }).
For your problem, you could just write a little wrapper function:
let curve depth coords = New DepthCurve([for (x, y) in coords -> New Coord(x, y)], depth)
used like this
let testCurve = curve 10. [(1., 2.); (3., 4.); ...]
When declaring your structures in the shortened record syntax, you should do it like this:
type Coord = float * float // Type-alias for a 2D-float-tuple
type DepthCurve = { coords : Coord list; depth : float }
let myCurve = { coords = [(1., 2.); ...], depth = 42. }
There is no reason why you should use a generic list, just specify Coord list (meaning List of Coords). And please note the difference between a list ([1; 2; 3]) and a tuple ((1, 2, 3)). The latter are much more suitable for representing coords.
Please take a look at this article on F# structures and types.
The answer depends from the way you construct your program.
For case you activly use functional paradigm (no mutation, high-order functions, pattern matching) i vote for three choices:
(* tuple with type constractor and any getters you need: *)
let makeCoord x y = (x,y)
let makeCurve depth coords = (depth,coords)
let addCurveCoord (depth,coords) coord = (depth, coord::coords)
let getCurveDepth (depth,_) = depth
let getCurveCoords (_,coords) = coords
let getFirstCurveCoord (_,coords) = List.hd coords
//...
(* or types described by Dario *)
(* or tagged unions for case you need specific access to parts of your data *)
for case you prefer OOP you can create simple object hierarchy.
The main advantage of FP is easy modification of your design at any step of program constraction. But of course, it cost to your by explicit state arguments. But may beat them by monadic expressions :)

Resources