In F#, any data can be stringify by function sprintf as following:
type someKindOfDataType = ...
let data : someKindOfDataType = ...
sprintf "%A" data
Can we have a reversal function to parse a string back to someKindOfDataType, like following:?
let parse<'someKingOfDataType> (s:string) : someKindOfDataType = ....
just like JSON.parse in javascript?
You are describing what is normally referred to as serialisation - converting from an in-memory data structure to a representation that can be transmitted over a network, which could be XML, JSON, binary etc. - and deserialisation - the reverse.
sprintf "%A" is designed to give a convenient visual representation of data, usually only for the purposes of development as opposed to in production. It does not actually do serialisation, since there is no way to deserialise.
If you want to serialise F# data to a string I would recommend using JSON via library such as Newtonsoft.Json.
Note that this will not produce strings that look similar to F# source code like sprintf "%A" does because the purpose is different. An example:
Newtonsoft.Json.JsonConvert.SerializeObject [|Some 3; None|]
// """[{"Case":"Some","Fields":[3]},null]"""
Newtonsoft.Json.JsonConvert.DeserializeObject<int option []> """[{"Case":"Some","Fields":[3]},null]"""
// [|Some 3; None|]
You need to provide the type to deserialise to and this operation may throw an exception if the string doesn't represent a valid instance of that type.
The standard .NET way is that normally you'll use a Parse or TryParse method in the class of the type you're trying to parse.
But in F# the TryParse function is not very friendly, since it uses an output parameter, still the F# compiler allows you to see it as a tuple, which makes things better but still you'll expect to get an option, here's an example:
let a = Int32.Parse "5"
let b =
match Int32.TryParse "5" with
| true, value -> Some value
| _ -> None
If you want to use a library F#+ has both functions parse and tryParse which does all the above for you:
#r #"FSharpPlus.dll"
open FSharpPlus
open System
let (a:int) = parse "5"
let (b:int option) = tryParse "5"
let (c: Net.IPAddress option) = tryParse "10.0.0.1"
// val a : int = 5
// val b : int option = Some 5
// val c : Net.IPAddress option = Some 10.0.0.1
It works as long as the type has either Parse or TryParse defined.
Related
I am trying to develop F# type provider.
It provides some DTOs (with the structure described in some external document) and a set of methods for processing them. The processing algorithm is based on reflection, and I want to have a single quotation representing it.
Generally, this algorithm must pass all method call arguments to the already written function serialize: obj -> MySerializationFormat, storing all results in a list, so I getting a value of MySerializationFormat list.
Code sample below shows, how I tried to do that for first time:
let serialize (value: obj) = ...
let processingCode: Expr list -> Expr =
fun args ->
let serializeArgExpr (arg: Expr) = <# serialize %%arg} #>
let argsExprs = List.map serializeArgExpr args
let serializedArgList =
List.foldBack (fun head tail -> <# (%head) :: (%tail)#>) argsExprs <# [] #>
// futher processing
At that point I faced with exception: In function serializeArgExpr the actual type of value in arg: Expr may vary, it can be some primitive type (e.g string, int, float), or some provided type. The problem is %% operator treats that arg as an expression of the obj type. Type check is performed on that line in Microsoft.FSharp.Quotations.Patterns module, in function fillHolesInRawExpr.
So, as the actual type of my term not matched the treated type for "hole" in the quotation, it throws invalidArg.
I have tried several technics to avoid these exceptions with casting operations in my quotation, but they don't work. Then I found Expr.Coerce(source, target) function, which looks like solving my problem. I have changed the code of serializeArgExpr to something like that:
let serializeArgExpr (arg: Expr) =
let value' = Expr.Coerce(value, typeof<obj>)
<# serialize %%value' } #>
Then faced a new strange exception:
The design-time type (point to a code line that uses my processingCode) utilized by a type provider was not found in the target reference assembly set
For me, it seems that my problem is to cast the type of value in any input Expr to an obj type. Thank you for diving in and trying to help.
I'm trying to implement a custom Arbitrary that generates glob syntax patterns like a*c?. I think my implementation is correct, it's just that, when running the test with Xunit, FsCheck doesn't seem to be using the custom arbitrary Pattern to generate the test data. When I use LINQPad however everything works as expected. Here's the code:
open Xunit
open FsCheck
type Pattern = Pattern of string with
static member op_Explicit(Pattern s) = s
type MyArbitraries =
static member Pattern() =
(['a'..'c']#['?'; '*'])
|> Gen.elements
|> Gen.nonEmptyListOf
|> Gen.map (List.map string >> List.fold (+) "")
|> Arb.fromGen
|> Arb.convert Pattern string
Arb.register<MyArbitraries>() |> ignore
[<Fact>]
let test () =
let prop (Pattern p) = p.Length = 0
Check.QuickThrowOnFailure prop
This is the output:
Falsifiable, after 2 tests (0 shrinks) (StdGen (1884571966,296370531)): Original: Pattern null with exception: System.NullReferenceException ...
And here is the code I'm running in LINQPad along with the output:
open FsCheck
type Pattern = Pattern of string with
static member op_Explicit(Pattern s) = s
type MyArbitraries =
static member Pattern() =
(['a'..'c']#['?'; '*'])
|> Gen.elements
|> Gen.nonEmptyListOf
|> Gen.map (List.map string >> List.fold (+) "")
|> Arb.fromGen
|> Arb.convert Pattern string
Arb.register<MyArbitraries>() |> ignore
let prop (Pattern p) = p.Length = 0
Check.Quick prop
Falsifiable, after 1 test (0 shrinks) (StdGen (1148389153,296370531)): Original: Pattern "a*"
As you can see FsCheck generates a null value for the Pattern in the Xunit test although I'm using Gen.elements and Gen.nonEmptyListOf to control the test data. Also, when I run it a couple times, I'm seeing test patterns that are out of the specified character range. In LINQPad those patterns are generated correctly. I also tested the same with a regular F# console application in Visual Studio 2017 and there the custom Arbitrary works as expected as well.
What is going wrong? Is FsCheck falling back to the default string Arbitrary when running in Xunit?
You can clone this repo to see for yourself: https://github.com/bert2/GlobMatcher
(I don't want to use Prop.forAll, because each test will have multiple custom Arbitrarys and Prop.forAll doesn't go well with that. As far as I know I can only tuple them up, because the F# version of Prop.forAll only accepts a single Arbitrary.)
Don't use Arb.register. This method mutates global state, and due to the built-in parallelism support in xUnit.net 2, it's undetermined when it runs.
If you don't want to use the FsCheck.Xunit Glue Library, you can use Prop.forAll, which works like this:
[<Fact>]
let test () =
let prop (Pattern p) = p.Length = 0
Check.QuickThrowOnFailure (Prop.forAll (MyArbitraries.Pattern()) prop)
(I'm writing this partially from memory, so I may have made some small syntax mistakes, but hopefully, this should give you an idea on how to proceed.)
If, on the other hand, you choose to use FsCheck.Xunit, you can register your custom Arbitraries in a Property annotation, like this:
[<Property(Arbitrary = [|typeof<MyArbitraries>|])>]
let test (Pattern p) = p.Length = 0
As you can see, this takes care of much of the boilerplate; you don't even have to call Check.QuickThrowOnFailure.
The Arbitrary property takes an array of types, so when you have more than one, this still works.
If you need to write many properties with the same array of Arbitraries, you can create your own custom attributes that derives from the [<Property>] attribute. Here's an example:
type Letters =
static member Char() =
Arb.Default.Char()
|> Arb.filter (fun c -> 'A' <= c && c <= 'Z')
type DiamondPropertyAttribute() =
inherit PropertyAttribute(
Arbitrary = [| typeof<Letters> |],
QuietOnSuccess = true)
[<DiamondProperty>]
let ``Diamond is non-empty`` (letter : char) =
let actual = Diamond.make letter
not (String.IsNullOrWhiteSpace actual)
All that said, I'm not too fond of 'registering' Arbitraries like this. I much prefer using the combinator library, because it's type-safe, which this whole type-based mechanism isn't.
I'm trying to use AutoMapper from F#, but I'm having trouble setting it up due to AutoMapper's heavy use of LINQ Expressions.
Specifically, the AutoMapper type IMappingExpression<'source, 'dest> has a method with this signature:
ForMember(destMember: Expression<Func<'dest, obj>>, memberOpts: Action<IMemberConfigurationExpression<'source>>)
This is typically used in C# like this:
Mapper.CreateMap<Post, PostsViewModel.PostSummary>()
.ForMember(x => x.Slug, o => o.MapFrom(m => SlugConverter.TitleToSlug(m.Title)))
.ForMember(x => x.Author, o => o.Ignore())
.ForMember(x => x.PublishedAt, o => o.MapFrom(m => m.PublishAt));
I made an F# wrapper that arranges things so that type inference can work. This wrapper allows me to translate the C# example above into something like this:
Mapper.CreateMap<Post, Posts.PostSummary>()
|> mapMember <# fun x -> x.Slug #> <# fun m -> SlugConverter.TitleToSlug(m.Title) #>
|> ignoreMember <# fun x -> x.Author #>
|> mapMember <# fun x -> x.PublishedAt #> <# fun m -> m.PublishAt #>
|> ignore
This code compiles, and it seems pretty clean as far as syntax and usage. However, at runtime AutoMapper tells me this:
AutoMapper.AutoMapperConfigurationException: Custom configuration for members is only supported for top-level individual members on a type.
I presume this is caused by the fact that I have to convert Expr<'a -> 'b> into Expression<Func<'a, obj>>. I convert the 'b to obj with a cast, which means my lambda expression is no longer simply a property access. I get the same error if I box the property value in the original quotation, and don't do any splicing at all inside forMember (see below). However, if I don't box the property value, I end up with Expression<Func<'a, 'b>> which does not match the parameter type that ForMember expects, Expression<Func<'a, obj>>.
I think that this would work if AutoMapper's ForMember was completely generic, but forcing the return type of the member access expression to be obj means that I can only use it in F# for properties that are already directly of type obj and not a subclass. I can always resort to using the overload of ForMember that takes the member name as a string, but I thought I'd check to see if anyone has a brilliant work-around before I give up on compile-time typo-checking.
I'm using this code (plus the LINQ part of F# PowerPack) to convert an F# quotation into a LINQ expression:
namespace Microsoft.FSharp.Quotations
module Expr =
open System
open System.Linq.Expressions
open Microsoft.FSharp.Linq.QuotationEvaluation
// http://stackoverflow.com/questions/10647198/how-to-convert-expra-b-to-expressionfunca-obj
let ToFuncExpression (expr:Expr<'a -> 'b>) =
let call = expr.ToLinqExpression() :?> MethodCallExpression
let lambda = call.Arguments.[0] :?> LambdaExpression
Expression.Lambda<Func<'a, 'b>>(lambda.Body, lambda.Parameters)
This is the actual F# wrapper for AutoMapper:
namespace AutoMapper
/// Functions for working with AutoMapper using F# quotations,
/// in a manner that is compatible with F# type-inference.
module AutoMap =
open System
open Microsoft.FSharp.Quotations
let forMember (destMember: Expr<'dest -> 'mbr>) (memberOpts: IMemberConfigurationExpression<'source> -> unit) (map: IMappingExpression<'source, 'dest>) =
map.ForMember(Expr.ToFuncExpression <# fun dest -> ((%destMember) dest) :> obj #>, memberOpts)
let mapMember destMember (sourceMap:Expr<'source -> 'mapped>) =
forMember destMember (fun o -> o.MapFrom(Expr.ToFuncExpression sourceMap))
let ignoreMember destMember =
forMember destMember (fun o -> o.Ignore())
Update:
I was able to use Tomas's sample code to write this function, which produces an expression that AutoMapper is satisfied with for the first argument to IMappingExpression.ForMember.
let toAutoMapperGet (expr:Expr<'a -> 'b>) =
match expr with
| Patterns.Lambda(v, body) ->
// Build LINQ style lambda expression
let bodyExpr = Expression.Convert(translateSimpleExpr body, typeof<obj>)
let paramExpr = Expression.Parameter(v.Type, v.Name)
Expression.Lambda<Func<'a, obj>>(bodyExpr, paramExpr)
| _ -> failwith "not supported"
I still need the PowerPack LINQ support to implement my mapMember function, but they both work now.
If anyone is interested, they can find the full code here.
Now that F# is happy to generate a Expression<Func<...>> directly from a fun expression, this is relatively easy to solve. The biggest problem now is that the F# compiler seems to get confused by the overloading of the ForMember method, and is unable to infer correctly what you want. This can be circumvented by defining an extension method with a different name:
type AutoMapper.IMappingExpression<'TSource, 'TDestination> with
// The overloads in AutoMapper's ForMember method seem to confuse
// F#'s type inference, forcing you to supply explicit type annotations
// for pretty much everything to get it to compile. By simply supplying
// a different name,
member this.ForMemberFs<'TMember>
(destGetter:Expression<Func<'TDestination, 'TMember>>,
sourceGetter:Action<IMemberConfigurationExpression<'TSource, 'TDestination, 'TMember>>) =
this.ForMember(destGetter, sourceGetter)
You can then use the ForMemberFs method more or less as the original ForMember is intended to work, e.g.:
this.CreateMap<Post, Posts.PostSummary>()
.ForMemberFs
((fun d -> d.Slug),
(fun opts -> opts.MapFrom(fun m -> SlugConverter.TitleToSlug(m.Title)))
I'm not quite sure how to fix the generated expression tree (that's doable by post-processing it, but it is pain to find out what AutoMapper expects). However, there are two alternatives:
As a first option - the expressions that you need to translate are fairly simple. They are mostly just method calls, property getters and uses of a variable. This means that it should be possible to write your own quotation to expression trees translator that produces exactly the code you want (then you can also add your own handling of obj, perhaps by calling Expression.Convert to build the expression tree). I wrote a simple quotation tranlsator as a sample, which should handle most of the stuff in your sample.
As a second option - if AutoMapper provides an option to specify just a property name - you could just use quotations of the form <# x.FooBar #>. These should be quite easy to deconstruct using the Patterns.PropertyGet pattern. The API should maybe look like this:
Mapper.CreateMap<Post, Posts.PostSummary>(fun post summary mapper ->
mapper |> mapMember <# post.Slug #> // not sure what the second argument should be?
|> ignoreMember <# post.Author #> )
Or, in fact, you could use this style of API even in the first case, because you don't need to write lambda expressions repeatedly for every single mapping, so maybe it is a bit nicer :-)
I just began toying around with F# in Mono and the following problem arose that I cannot quite understand. Looking up information on printfn and TextWriterFormat didn't bring enlightenment either, so I thought I'm going to ask here.
In FSI I run the following:
> "hello";;
val it : string = "hello"
> printfn "hello";;
hello
val it : unit = ()
Just a normal string and printing it. Fine. Now I wanted to declare a variable to contain that same string and print it as well:
> let v = "hello" in printfn v ;;
let v = "hello" in printfn v ;;
---------------------------^
\...\stdin(22,28): error FS0001: The type 'string' is not compatible with the type 'Printf.TextWriterFormat<'a>'
I understood from my reading that printfn requires a constant string. I also understand that I can get around this problem with something like printfn "%s" v.
However, I'd like to understand what's going on with the typing here. Clearly, "hello" is of type string as well as v is. Why is there a type problem then? Is printfn something special? As I understand it the compiler already performs type-checking on the arguments of the first string, such that printfn "%s" 1 fails.. this could of course not work with dynamic strings, but I assumed that to be a mere convenience from the compiler-side for the static case.
Good question. If you look at the type of printfn, which is Printf.TextWriterFormat<'a> -> 'a, you'll see that the compiler automatically coerces strings into TextWriterFormat objects at compile time, inferring the appropriate type parameter 'a. If you want to use printfn with a dynamic string, you can just perform that conversion yourself:
let s = Printf.TextWriterFormat<unit>("hello")
printfn s
let s' = Printf.TextWriterFormat<int -> unit>("Here's an integer: %i")
printfn s' 10
let s'' = Printf.TextWriterFormat<float -> bool -> unit>("Float: %f; Bool: %b")
printfn s'' 1.0 true
If the string is statically known (as in the above examples), then you can still have the compiler infer the right generic argument to TextWriterFormat rather than calling the constructor:
let (s:Printf.TextWriterFormat<_>) = "hello"
let (s':Printf.TextWriterFormat<_>) = "Here's an integer: %i"
let (s'':Printf.TextWriterFormat<_>) = "Float: %f; Bool: %b"
If the string is truly dynamic (e.g. it's read from a file), then you'll need to explicitly use the type parameters and call the constructor as I did in the previous examples.
This is only somewhat related to your question, but I think it's a handy trick. In C#, I often have template strings for use with String.Format stored as constants, as it makes for cleaner code:
String.Format(SomeConstant, arg1, arg2, arg3)
Instead of...
String.Format("Some {0} really long {1} and distracting template that uglifies my code {2}...", arg1, arg2, arg3)
But since the printf family of methods insist on literal strings instead of values, I initially thought that I couldn't use this approach in F# if I wanted to use printf. But then I realized that F# has something better - partial function application.
let formatFunction = sprintf "Some %s really long %i template %i"
That just created a function that takes a string and two integers as input, and returns a string. That is to say, string -> int -> int -> string. It's even better than a constant String.Format template, because it's a strongly-typed method that lets me re-use the template without including it inline.
let foo = formatFunction "test" 3 5
The more I use F#, the more uses I discover for partial function application. Great stuff.
I don't think that it is correct to say that the literal value "hello" is of type String when used in the context of printfn "hello". In this context the compiler infers the type of the literal value as Printf.TextWriterFormat<unit>.
At first it seemed strange to me that a literal string value would have a different inferred type depending on the context of where it was used, but of course we are used to this when dealing with numeric literals, which may represent integers, decimals, floats, etc., depending on where they appear.
If you want to declare the variable in advance of using it via printfn, you can declare it with an explicit type...
let v = "hello" : Printf.TextWriterFormat<unit> in printfn v
...or you can use the constructor for Printf.TextWriterFormat to convert a normal String value to the necessary type...
let s = "foo" ;;
let v = new Printf.TextWriterFormat<unit>(s) in printfn v ;;
As you correctly observe, the printfn function takes a "Printf.TextWriterFormat<'a>" not a string. The compiler knows how to convert between a constant string and a "Printf.TextWriterFormat<'a>", but not between a dynamic string and a "Printf.TextWriterFormat<'a>".
This begs the question why can't it convert between a dynamic string and a "Printf.TextWriterFormat<'a>". This is because the compiler must look at the contents of the string to and determine what control characters are in it ( i.e. %s %i etc), from this is it works out the type of the type parameter of "Printf.TextWriterFormat<'a>" (i.e. the 'a bit). This is a function that is returned by the printfn function and means that the other parameters accepted by printfn are now strongly typed.
To make this a little clear in your example "printfn "%s"" the "%s" is converted into a "Printf.TextWriterFormat unit>", meaning the type of "printfn "%s"" is string -> unit.
I've read through a good chunk of Expert F# and am working on building an actual application. While debugging, I've grown accustomed to passing fsi commands like this to make things legible in the repl window:
fsi.AddPrinter(fun (x : myType) -> myType.ToString())
I would like to extend this to work with the printf formatter, so I could type e.g.
printf "%A" instanceOfMyType
and control the output for a custom type. The book implies that this can be done (p 93, "Generic structural formatting can be extended to work with any user-defined data types,
a topic covered on the F# website"), but I have failed to find any references as to how to actually accomplish this. Does anyone know how? Is it even possible?
Edit:
I should have included a code sample, it's a record type that I'm dealing with, e.g.
type myType =
{a: int}
override m.ToString() = "hello"
let t = {a=5}
printfn "%A" t
printfn "%A" (box t)
both print statements yield:
{a = 5;}
It looks like the Right Way to do this in F# 2.0 is by using the StructuredFormatDisplay attribute, for example:
[<StructuredFormatDisplay("hello {a}")>]
type myType = {a: int}
In this example, instead of the default {a = 42;}, you would get hello 42.
This works the same way for object, record, and union types. And although the pattern must be of the format "PreText {PropertyName} PostText" (PreText and PostText being optional), this is actually more powerful than ToString() because:
PropertyName can be a property of any type. If it is not a string, then it will also be subject to structured formatting. Don Syme's blog gives an example of recursively formatting a tree in this way.
It may be a calculated property. So you could actually get ToString() to work for record and union types, though in a rather round-about way:
[<StructuredFormatDisplay("{AsString}")>]
type myType =
{a: int}
override m.ToString() = "hello"
member m.AsString = m.ToString() // a property that calls a method
By the way, ToString() will always be used (even for record and union types) if you call printfn "%O" instead of printfn "%A".
Hmm... I vaguely recall some changes to this, but I forget if they happened before or after the CTP (1.9.6.2).
In any case, on the CTP, I see that
type MyType() =
override this.ToString() = "hi"
let x = new MyType()
let xs = Array.create 25 x
printfn "%A" x
printfn "%A" xs
when evaluated in the VFSI window does what I would want, and that
x;;
xs;;
also prints nicely. So, I guess I am unclear how this differs from what is desired?
If you override ToString method, that should do.