Thoth.Json.Net – Decoder as a Functor, is it possible? - f#

I have found this superb JSON library for F#, it's inspired by Elm's Json.Decode and it defines a basic Decoder type like this:
type Decoder<'T> = string -> obj -> Result<'T, DecoderError> (here)
There are functions like Decode.map and I wish I could make it F#+ compatible, so I could use it like:
let customerId = Decode.string |>> CustomerId
(see |>> infix version of generic map)
As far as I can see, to make a 3rd party library use F#+ concepts like Functors, one needs to extend the 3rd party type with static member Map, but the Decoder<'T> is just an abbreviation.
Is there any solution? Did anyone try?
P.S.
My solution so far is a custom binding:
let (<!>) = Decode.map
let customerId: Decoder<CustomerId> = CustomerId <!> Decode.string
let submitId: Decoder<SubmitId> = SubmitId <!> Decode.string
let currency: Decoder<Currency> = Currency <!> Decode.string
// etc…

The problem is that you don't control the code. If you had control over it, a solution would be:
Implement Decoder as a concrete type as opposed to a type alias. A type alias can't have additional members, because it's not really another type. Library authors should use single case discriminated unions, now that you can make them structs with nearly zero overhead.
Add the member Map with the required signature.
Alternatively, if extensions members becomes visible for trait constraints in a future F# version, you would be able just extend the type with the Map function, maybe with some undesired effects as it's a type alias for a function with 2 arguments.
So, I think the best you can do is what you already showed.
As a side note, you might be interested in having a look at Fleece which also provides decoders, but it also goes one step further and provides you codecs which goes in both directions (and you can map and <*> over it).

Related

What is the point of op_Quotation if it cannot be used?

According the F# specification for operator overloading
<# #> op_Quotation
<## ##> op_QuotationUntyped
is given as with many other operators. Unless I'm missing something I don't believe that I can use this for custom types, so why is it listed?
I think you are right that there is no way of actually using those as custom operators. I suspect those are treated as operators in case this was useful, at some point in the future of the language, for some clever new feature.
The documentation really merely explains how the names of the operators get encoded. For non-special operator names, F# encodes those in a systematic way. For the ones listed in the page, it has a special nicer name. Consider this type:
type X() =
static member (<^><>) (a:int,b:int) = a + b
static member (<# #>) (a:int,b:int) = a + b
If you look at the names of those members:
[ for m in typeof<X>.GetMembers() -> m.Name ]
You see that the first operator got compiled as op_LessHatGreaterLessGreater, while the second one as op_Quotation. So this is where the name memntioned in the table comes in - it is probably good this is documented somewhere, but I think you're right, that this is not particularly useful!

Using System.String.Split from F#

I would like to use the .NET CLR version of String.Split in F#. Specifically I would like to use this code:
let main argv =
let s = "Now is the time for FOO good men to come to the aide of their country"
let sepAry = [|"FOO"; "BAR"|]
let z1 = s.Split sepAry
0 // return an integer exit code
This fails to compile however, due to the fact (I believe) that the version of Split in F# is implemented differently than the one in .Net 4.5.
The version from .NET that I would like is:
Split(String[], StringSplitOptions) Returns a string array that contains the substrings in this string that are delimited by elements of a specified string array. A parameter specifies whether to return empty array elements.
I understand that I am getting the F# version of Split, which formerly resided in the PowerPack and that is why the implementation differs from the CLR version.
What is the best way to get what I want? Is it possible to override the F# version of Split and use the .Net version? Is it possible to extend the F# version and if so, how?
The overload you want to use expects a second argument.
let z1 = s.Split (sepAry, System.StringSplitOptions.None)
It's not an “F# version of Split”, it's exactly that Split you see in C#.
2 things are the problem here:
For .NET BCL you need to specify (), because the parameters are declared in different way using tuples (See http://msdn.microsoft.com/en-us/library/dd483468.aspx)
Only the char[] overload exists without StringSplitOptions. If you want to use a string array, you also need to specify StringSplitOptions.
You could create your own F# overload method, that provides a default for the stringsplitoptions.
Kirelagin is right, the Split method on String your trying to use doesn't exist, it's only available for char arrays with no secondary argument. You have to resort to this version: http://msdn.microsoft.com/en-us/library/tabh47cf.aspx. Also you have to use parentheses around your arguments when calling none-f# .NET apis because the arguments in C# are defined as a tuple.
You could of cause define your own extension-method on String, this way you don't have to specify None all the time if that is your expected default behavior
type System.String with
member x.Split(separator : (string [])) = x.Split(separator, System.StringSplitOptions.None)

Nullablle<>'s and "null" in F#

I'm calling functions in the XNA framework from F# that accept Nullable values. Now, in C#, you would just call:
foo(arg1, arg2, null, arg4)
Now, I tried that in F#, but it doesn't like it. It says: "Error 9 Type constraint mismatch. The type 'a is not compatible with type System.Nullable The type 'System.Nullable' does not have 'null' as a proper value."
I understand why this is happening, sort of, but it seems really inconvenient. All I'm doing now is, to make life easier, instead of repeatedly typing (Nullable<Rectangle>)null everytime I call the function, I just did let nullRect = (Nullable<Rectangle>)null, and use nullRect. This seems really stupid, especially since I'd have to do that for every nullable type I interact with. Is there a better, more idiomatic way to handle this?
Here's what I'd do:
[<GeneralizableValue>]
let nl<'a when 'a : struct
and 'a : (new : unit -> 'a)
and 'a :> System.ValueType> : System.Nullable<'a> =
unbox null
Now you can use nl wherever you would have used null before.
EDIT
As Tomas notes, this can be written much more concisely as:
let nl = System.Nullable<_>()
If you don't want to use kvb's very clever answer, in many cases you can omit the specific type and just use Nullable<_>() - F# can infer what sort of Nullable you mean.

Questions about the definition of lazy

On line 5633 in prim-types.fs (v1.9.7.8) there is the following type abbreviation:
type 'T ``lazy`` = Lazy<'T>
I have a few questions about it.
What do the double backticks mean?
Is this definition equivalent to type lazy<'T> = Lazy<'T>? (If not, how is it different?)
The double back ticks are a way of allowing an F# keyword to be used as an identifier. Another example would be
let ``let`` = 42
To answer the second half of your question, generic types in F# can be specified using either the O'Caml-style syntax where the generic parameter precedes the type (e.g 'a list, int array, etc.), or the .NET-style with angle brackets (e.g. list<'a>, array<int>, etc.), so the two definitions are indeed basically equivalent (except that your version as written is syntactically invalid because lazy is a keyword). For multi-parameter generic types, the O'Caml style is deprecated and will generate a warning (e.g. let (m:(int,string) Map) = Map.empty should be rewritten as let (m:Map<int,string>) = Map.empty).

Point-free style with objects/records in F#

I'm getting stymied by the way "dot notation" works with objects and records when trying to program in a point-free functional style (which I think is a great, concise way to use a functional language that curries by default).
Is there an operator or function I'm missing that lets me do something like:
(.) object method instead of object.method?
(From what I was reading about the new ? operator, I think it works like this. Except it requires definition and gets into the whole dynamic binding thing, which I don't think I need.)
In other words, can I apply a method to its object as an argument like I would apply a normal function to its argument?
Short answer: no.
Longer answer: you can of course create let-bound functions in a module that call a method on a given type... For example in the code
let l = [1;2;3]
let h1 = l.Head
let h2 = List.hd l
there is a sense in which "List.hd" is the version of what you want for ".Head on a list". Or locally, you can always do e.g.
let AnotherWay = (fun (l:list<_>) -> l.Head)
let h3 = AnotherWay l
But there is nothing general, since there is no good way to 'name' an arbitrary instance method on a given type; 'AnotherWay' shows a way to "make a function out of the 'Head' property on a 'list<_>' object", but you need such boilerplate for every instance method you want to treat as a first-class function value.
I have suggested creating a language construct to generalize this:
With regards to language design
suggestions, what if
SomeType..Foo optArgs // note *two* dots
meant
fun (x : SomeType) -> x.Foo optArgs
?
In which case you could write
list<_>..Head
as a way to 'functionize' this instance property, but if we ever do anything in that arena in F#, it would be post-VS2010.
If I understand your question correctly, the answer is: no you can't. Dot (.) is not an operator in F#, it is built into the language, so can't be used as function.

Resources