I would like to define a type such as:
type blah =
AThing
| AnotherThing
with
static member ofString : string -> blah
override x.ToString () : string
I would like to make sure that the two methods are always guaranteed to be consistent. A good way of doing this would be to construct two maps from the same list of pairs, and then turn them into the obvious implementations of the two methods. Roughly:
let pairs = [Athing, "AThing"; AnotherThing, "AnotherThing"]
let tostr = Map.ofList pairs
let toblah = pairs |> List.map swap |> Map.ofList
I think this code can only be defined in a static member function. The static bit is implied by it needing to be accessible from ofString, which is static. It cannot be defined before the type, since the list relies on it. It cannot be defined afterwards because F# does not allow methods to be just declared and implemented later (in the same way that e.g. C++ would). So that leaves the choice between a static member and a static let. The compiler says that static lets are not allowed in an augmentation. (?)
The code works fine when put into a static member function, however it makes the maps every time they are needed. Needless to say, this is even less efficient than linear search. How do I do it correctly please? Many thanks.
This compiles (with a warning)
type blah =
AThing
| AnotherThing
let pairs = [AThing, "AThing"; AnotherThing, "AnotherThing"]
let tostr = Map.ofList pairs
let toblah = pairs |> List.map (fun (x,y)->y,x) |> Map.ofList
type blah
with
static member ofString s = toblah.[s]
override x.ToString () = tostr.[x]
and demonstrates an augmentation (define the type, do other code, then do type blah with to define more members).
Here's the code that works as required:
type blahFactory() =
static let pairs = printf "array initialized; "; [AThing, "AThing"; AnotherThing, "AnotherThing"]
static member tostr = Map.ofList pairs
static member toblah = pairs |> List.map swap |> Map.ofList
and blah =
| AThing
| AnotherThing
with
static member ofString (string) = blahFactory.toblah.[string]
override x.ToString () = blahFactory.tostr.[x]
I've placed printf instruction to demonstrate the array is initialized just once.
Several thoughts you may consider useful.
First, using DU is overhead for sample provided. If your data is that simple, you may consider enum types.
If you really mean DU, that may be sign of possible problems in the future. Consider this:
type blah =
| AThing of string
| AnotherThing of int * int
Both construction and comparison will be impossible in this case.
Do you have any reasons not to use standard XML serialization?
I don't get your point. What's wrong with:
type blah =
| AThing
| AnotherThing
with
static member ofString = function
| "AThing" -> AThing
| "AnotherThing" -> AnotherThing
| _ -> failwith "Unwellformed string"
override x.ToString () =
match x with
| AThing -> "AThing"
| AnotherThing -> "AnotherThing"
Pattern matching is Θ(1) which is extremely efficient in F#.
I believe you were trying to do the following: for any Discriminated Union have an ability to go from particular DU case to its name and back without burden of hardcoding the relationship for each pair, which have place in both answers by Brian and pad.
If you sacrifice override of ToString() in lieu of the equivalent static member it can be done with the following approach:
open Microsoft.FSharp.Reflection
type Blah =
| AThing
| AnotherThing
[<AutoOpenAttribute>]
module BlahExt =
let cases = FSharpType.GetUnionCases typeof<Blah>
let toBlah = dict [for case in cases do yield (case.Name, FSharpValue.MakeUnion(case, [||]) :?> Blah)]
let fromBlah = dict [for case in cases do yield ((FSharpValue.MakeUnion(case, [||]) :?> Blah), case.Name)]
type Blah
with
static member ofString name =
if toBlah.ContainsKey name then (toBlah.Item name) else failwith "bad string"
static member toString x = fromBlah.Item x
Now printfn "ofString: %A" (Blah.ofString "AThing") shows union case AThing and vice versa printfn "toString: %s" (Blah.toString AThing) shows string AThing.
You can notice that I did not list members of your DU whatsoever, this is achieved once thru reflection and guaranteed to be correct mapping automagically. This approach will work for any number of unit cases - two or two hundreds - without any need to hardcode the particular cases.
Related
F# does not (currently) support type-classes. However, F# does support the OOP aspects of C#.
I was wondering, what is lost doing this approach compared to true type-classes?
// A concrete type
type Foo =
{
Foo : int
}
// "Trait" for things that can be shown
type IShowable =
abstract member Show : unit -> string
module Showable =
let show (showable : IShowable) =
showable.Show()
// "Witness" of IShowable for Foo
module Foo =
let asShowable (foo : Foo) =
{
new IShowable with
member this.Show() = string foo.Foo
}
// Slightly awkward usage
{ Foo = 123 }
|> Foo.asShowable
|> Showable.show
|> printfn "%s"
Your suggestion works for simple typeclasses that operate on a single value of a type, like Show. However, what happens when you need a typeclass that isn't so object-oriented? For example, when we want to add two numbers, neither one corresponds to OO's this object:
// not real F#
typeclass Numeric<'a> = // e.g. Numeric<int> or Numeric<float>
abstract member (+) : 'a -> 'a -> 'a // e.g. 2 + 3 = 5 or 2.0 + 3.0 = 5.0
...
Also, keep in mind that many useful typeclasses require higher-kinded types. For example, consider the monad typeclass, which would look something like this:
// not real F#
typeclass Monad<'m<_>> = // e.g. Monad<Option<_>> or Monad<Async<_>>
abstract member Return<'a> : 'a -> 'm<'a>
abstract member Bind<'a, 'b> : 'm<'a> -> ('a -> 'm<'b>) -> 'm<'b>
There's no good way to do this with .NET interfaces.
Higher-kinded type classes are indeed impossible to model with interfaces, but that's just because F# does not support higher-kindedness, not because of type classes themselves.
The deeper thing to note is that your encoding isn't actually correct. Sure, if you just need to call show directly, you can do asShowable like that, but that's just the simplest case. Imagine you needed to pass the value to another function that wanted to show it later? And then imagine it was a list of values, not a single one:
let needsToShow (showable: IShowable) (xs: 'a list) =
xs |> List.iter (fun x -> ??? how do I show `x` ???)
No, this wouldn't do of course. The key is that Show should be a function 'a -> string, not unit -> string. And this means that IShowable itself should be generic:
// Haskell: class Showable a where show :: a -> String
type IShowable<'a> with
abstract member Show : 'a -> string
// Haskell: instance Showable Foo where show (Foo i) = show i
module Foo =
let showable = { new IShowable<Foo> with member _.Show foo = string foo.Foo }
// Haskell: needsToShow :: Show a => [a] -> IO ()
let needsToShow (showable: IShowable<'a>) (xs: 'a list) =
xs |> List.iter (fun x -> printfn "%s" (showable.Show x))
// Haskell: needsToShow [Foo 1, Foo 42]
needsToShow Foo.showable [ { Foo: 1 }; { Foo: 42 } ]
And this is, essentially, what type classes are: they're indeed merely dictionaries of functions that are passed everywhere as extra parameters. Every type has such dictionary either available right away (like Foo above) or constructable from other such dictionaries, e.g.:
type Bar<'a> = Bar of 'a
// Haskell: instance Show a => Show (Bar a) where show (Bar a) = "Bar: " <> show a
module Bar =
let showable (showA: IShowable<'a>) =
{ new IShowable<Bar<'a>> with member _.Show (Bar a) = "Bar: " + showA.Show a }
This is completely equivalent to type classes. And in fact, this is exactly how they're implemented in languages like Haskell or PureScript in the first place: like dictionaries of functions being passed as extra parameters. It's not a coincidence that constraints on function type signatures even kinda look like parameters - just with a fat arrow instead of a thin one.
The only real difference is that in F# you have to do that yourself, while in Haskell the compiler figures out all the instances and passes them for you.
And this difference turns out to be kind of important in practice. I mean, sure, for such a simple example as Show for the immediate parameter, you can just pass the damn instance yourself. And even if it's more complicated, I guess you could suck it up and pass a dozen extra parameters.
But where this gets really inconvenient is operators. Operators are functions too, but with operators there is nowhere to stick an extra parameter (or dozen). Check this out:
x = getY >>= \y -> getZ y <&> \z -> y + 42 > z
Here I used four operators from four different classes:
>>= comes from Monad
<&> from Functor
+ from Num
> from Ord
An equivalent in F# with passing instances manually might look something like:
let x =
bind Foo.monad getY <| fun y ->
map Bar.functor (getZ y) <| fun z ->
gt Int.ord (add Int.num y 42) z
Having to do that everywhere is quite unreasonable, you have to agree.
And this is why many F# operators either use SRTPs (e.g. +) or rely on "known" interfaces (e.g. <) - all so you don't have to pass instances manually.
I am fairly new to f#, but I want to know if it is possible to make a function that accepts multiple types of variables.
let add x y = x + y
let integer = add 1 2
let word = add "He" "llo"
Once a function use a type of variable it cannot accept another one.
You need to read about statically resolved type parameters and inline functions. It allows to create functions which may take any type that supports operation and/or have member. So your add function should be defined this way:
let inline add x y = x + y
Don't overuse inlined functions because their code inlined in call site and may increase assembly size, but may increase performance (test each case, don't make predictions!). Also inlined function are supported only by F# compiler and may not work with other languages (important when designing libraries).
Example of SRTP magic:
let inline (|Parsed|_|) (str: string) =
let mutable value = Unchecked.defaultof<_>
let parsed = ( ^a : (static member TryParse : string * byref< ^a> -> bool) (str, &value))
if parsed then
Some value
else
None
match "123.3" with
| Parsed 123 -> printfn "int 123"
| Parsed 123.4m -> printfn "decimal 123.4"
| Parsed 123.3 -> printfn "double 123.3"
// | Parsed "123.3" -> printfn "string 123.3" // compile error because string don't have TryParse static member
| s -> printfn "unmatched %s" s
I created a nested Discriminated Union (DU) as follows:
type OptimizationPeriod = | All
| Long
| Short
type OptimizationCriterion = | SharpeRatio of OptimizationPeriod
| InformationRatio of OptimizationPeriod
| CalmarRatio of OptimizationPeriod
and also a non-nested DU:
type Parallelism = Sequential | PSeq
I have a JSON configuration file with strings that define the DU cases. The following function manages to identify the case of the non-nested Parallelism DU :
let stringToDUCase<'t> (name: string) : 't =
let dUCase =
Reflection.FSharpType.GetUnionCases( typeof<'t> )
|> Seq.tryFind (fun uc -> uc.Name = name)
|> Option.map (fun uc -> Reflection.FSharpValue.MakeUnion( uc, [||] ) :?> 't)
match dUCase with
| Some x -> x
| _ -> let msg = sprintf "config.json - %s is not a case in DU %A" name typeof<'t>
failwith msg
Note: I certainly copied it from somewhere as the function is a bit over my head, apologies to the author for not remembering where it came from.
Unfortunately this function fails to identify the case for the nested DU:
stringToDUCase<OptimizationCriterion> config.Trading.Criterion
System.Exception: config.json - SharpeRatio All is not a case in DU FractalTypes.OptimizationCriterion
Two questions:
1) I was able to write a function that deals specifically with the OptimizationCriterion DU and is able to identify the case. Is there a generic function along the lines of stringToDUCase that could do the same?
2) Would it be better to use a tuple of type OptimizationCriterion*OptimizationPeriod instead of a nested DU? (I probably would have to call stringToDUCase twice, but that is not a problem)
An "empty" DU case like All is just a value, but a "non-empty" DU case like SharpeRatio is actually a function that takes one value and returns the type. In this case, SharpeRatio has the type OptimizationPeriod -> OptimizationCriterion.
Your existing stringToDUCase function always passes an empty array into MakeUnion (implying an empty DU case). So here's a modified version of the function that works for any DU case:
let stringToParamDUCase<'t> (name: string) =
Reflection.FSharpType.GetUnionCases(typeof<'t>)
|> Seq.tryFind (fun uc -> uc.Name = name)
|> Option.map (fun uc ->
fun (parameters:obj []) -> Reflection.FSharpValue.MakeUnion(uc, parameters) :?> 't)
|> Option.defaultWith (fun () ->
failwith (sprintf "config.json - %s is not a case in DU %A" name typeof<'t>))
Note that it returns a function of obj [] -> 't. I've also simplified the error handling a little bit.
This is how you might use it:
let myOptimizationPeriod = stringToParamDUCase<OptimizationPeriod> "All" [||]
let f = stringToParamDUCase<OptimizationCriterion> "SharpeRatio"
let myOptimizationCriterion = f [|All|]
I think the existing answer should answer your question directly. However, I think it is worth making two additional points. First, it might be easier if you represented your OptimizationCriterion as a record, because all your DU cases contain the same value:
type OptimizationPeriod =
| All | Long | Short
type OptimizationRatio =
| SharpeRatio | InformationRatio | CalmanRatio
type OptimizationCriterion =
{ Ratio : OptimizationRatio
Period : OptimizationPeriod }
This happens to solve your problem too, because now you only need DUs without parameters, but I think it is also better design, because you avoid duplicating the second parameter.
Second, I don't think you really need to go with a fancy custom reflection-based function for deserialization. If you want to store your data in a JSON, you should either use standard library (Newtonsoft.JSON or Chiron will do just fine), or you can write this directly using something like JsonValue from F# Data, but using custom reflection code is a quick way leading to unmaintainable code.
I am trying to emulate a system of type classes in F#; I would like to create pair printer which automatically instantiates the right series of calls to the printing functions. My latest try, which is pasted here, fails miserably since F# cannot identify the right overload and gives up immediately:
type PrintableInt(x:int) =
member this.Print() = printfn "%d" x
let (!) x = PrintableInt(x)
type Printer() =
static member inline Print< ^a when ^a : (member Print : Unit -> Unit)>(x : ^a) =
(^a : (member Print : Unit -> Unit) x)
static member inline Print((x,y) : 'a * 'b) =
Printer.Print(x)
Printer.Print(y)
let x = (!1,!2),(!3,!4)
Printer.Print(x)
Is there any way to do so? I am doing this in the context of game development, so I cannot afford the runtime overhead of reflection, retyping and dynamic casting: either I do this statically through inlining or I don't do it at all :(
What you're trying to do is possible.
You can emulate typeclasses in F#, as Tomas said maybe is not as idiomatic as in Haskell. I think in your example you are mixing typeclasses with duck-typing, if you want to go for the typeclasses approach don't use members, use functions and static members instead.
So your code could be something like this:
type Print = Print with
static member ($) (_Printable:Print, x:string) = printfn "%s" x
static member ($) (_Printable:Print, x:int ) = printfn "%d" x
// more overloads for existing types
let inline print p = Print $ p
type Print with
static member inline ($) (_Printable:Print, (a,b) ) = print a; print b
print 5
print ((10,"hi"))
print (("hello",20), (2,"world"))
// A wrapper for Int (from your sample code)
type PrintableInt = PrintableInt of int with
static member ($) (_Printable:Print, (PrintableInt (x:int))) = printfn "%d" x
let (!) x = PrintableInt(x)
let x = (!1,!2),(!3,!4)
print x
// Create a type
type Person = {fstName : string ; lstName : string } with
// Make it member of _Printable
static member ($) (_Printable:Print, p:Person) = printfn "%s, %s" p.lstName p.fstName
print {fstName = "John"; lstName = "Doe" }
print (1 ,{fstName = "John"; lstName = "Doe" })
Note: I used an operator to avoid writing the constraints by hand, but in this case is also possible to use a named static member.
More about this technique here.
What you're trying to do is not possible (edit: apparently, it can be done - but it might not be idiomatic F#), because the constraint language cannot capture the constraints you need for the second Print operation. Basically, there is no way to write recursive constraints saying that:
Let C be a constraint specifying that the type either provides Print or it is a two-element tuple where each element satisfies C.
F# does not support type-classes and so most of the attempts to emulate them will (probably) be limited in some way or will look very unnatural. In practice, instead of trying to emulate solutions that work in other languages, it is better to look for an idiomatic F# solution to the problem.
The pretty printing that you're using as a sample would be probably implemented using Reflection or by wrapping not just integers, but also tuples.
In F# and OCaml I wind up writing a lot of code like
type C = Blah of Whatever
let d = Blah (createWhatever ()) // so d is type C
...
let x = match d with | Blah b -> b
What I'd like is this
...
let x = peel d
Where peel would work for any constructor/discriminator.
Surely I'm not the only one annoyed by this.
edit:
Good answers, but I don't have the rep to vote on them.
How about this situation?
member self.Length = match self with | L lab -> lab.Length
It is not possible to do that safely : if peel was a function, what would be its type ? It cannot be typed and therefore cannot be a "good guy" in the language.
You may :
use reflection (in F#) or type-breaking functions (in OCaml it's the Obj module), but you will get something unsafe with an imprecise type, so it's rather ugly and "use at your own risk"
use metaprogramming to generate different versions of peel at each type for you. For example, using the type-conv OCaml tool, you may have type blah = Blah of something define a function peel_blah implicitly, and type foo = Foo of something define peel_foo.
The better solution imho is... not to need such a peel in the first place. I see two possibilities:
You may use clever patterns instead of a function : by using let (Blah whatever) = f x, or fun (Blah whatever) -> ..., you don't need an unpacking function anymore.
Or you may, instead of writing type blah = Blah of what, write
type blah = (blah_tag * whatever) and blah_tag = Blah
This way, you don't have a sum type but a product type (you write (Blah, whatever)), and your peel is just snd. You still have a different (incompatible) type for each blah, foo etc, but a uniform access interface.
As mentioned, the let is convenient to do a pattern matching.
If you want to access the value in the middle of an expression, where patterns are not allowed, I suggest adding a member to the types:
type C = Blah of int
with member c.Value = match c with Blah x -> x
let x = Blah 5
let y = Blah 2
let sum = x.Value + y.Value
I would write this instead:
type C = Blah of Whatever
let d = Blah (createWhatever ()) // so d is type C
...
let (Blah x) = d
For your second situation, I like Laurent's member x.Value = match x with Blah v -> v.
Works for DUs...will need tweaking to work with class constructors:
open Microsoft.FSharp.Reflection
let peel d =
if obj.ReferenceEquals(d, null) then nullArg "d"
let ty = d.GetType()
if FSharpType.IsUnion(ty) then
match FSharpValue.GetUnionFields(d, ty) with
| _, [| value |] -> unbox value
| _ -> failwith "more than one field"
else failwith "not a union type"
By the way: I wouldn't typically do something like this, but since you asked...