No, there's no good way to do this using F#'s built-in constructs. However, you could build your own reusable active pattern for this sort of thing.
No, there's no good way to do this using F#'s built-in constructs. However, you could build your own reusable active pattern for this sort of thing: open Microsoft.FSharp. Reflection open Microsoft.FSharp.
Quotations open Microsoft.FSharp.Quotations. DerivedPatterns open Microsoft.FSharp.Quotations. Patterns let (|UC|_|) e o = match e with | Lambdas(_,NewUnionCase(uc,_)) | NewUnionCase(uc,) -> if (box o = null) then // Need special case logic in case null is a valid value (e.g.Option.
None) let attrs = uc.DeclaringType. GetCustomAttributes(typeof, false) if attrs. Length = 1 && (attrs.0 :?
> CompilationRepresentationAttribute). Flags &&& CompilationRepresentationFlags. UseNullAsTrueValue enum 0 && uc.GetFields().
Length = 0 then Some else None else let t = o.GetType() if FSharpType. IsUnion t then let uc2, fields = FSharpValue. GetUnionFields(o,t) let getGenType (t:System.
Type) = if t. IsGenericType then t. GetGenericTypeDefinition() else t if uc2.
Tag = uc. Tag && getGenType (uc2. DeclaringType) = getGenType (uc. DeclaringType) then Some(fields |> List.
OfArray) else None else None | _ -> failwith "The UC pattern can only be used against simple union cases" Now your function might look something like this: let rec getSafeValue (item:obj) = match item with | :? String as str -> "'" + str + "'" | UC v -> getSafeValue v | UC -> "null" | _ as v -> v.ToString().
That's a neat way to do it. I ended up doing something similar. – kolosy Jul 1 '10 at 4:03.
This can't work in F# without covariance. Assuming that you're happy for v to be of type obj, you want to be able to treat Option as if it was Option. Without covariance, Option and Option are independent types.
Just to be clear, . NET (and thus F#) doesn't actually have covariance. – Ganesh Sittampalam Jul 1 '10 at 7:44.
When I put your code in F# Interactive, it seems to make 'record' a generic param. Maybe it works differently in the normal compiler. Anyway, it is probably picking up that obj type due to the first argument of GetValue being type obj.
I'm sorry I can't test this right now, but give this a shot. The box function uses a generic param, so that might do the trick. Let rec getSafeValue record (prop: PropertyInfo) = match prop.
GetValue(box record, null) with | :? String as str -> "'" + str + "'" | :? Option as opt -> match opt with | Some v -> getSafeValue v prop | None -> "null" | _ as v -> v.ToString().
Same deal - it constrains both record and opt to type 'a – kolosy Jun 30 '10 at 16:58.
Some v -> getSafeValue v prop will only work if v is of the same type as record. (or deriving from that that type) otherwise the first line will fail. You can't say prop.
GetValue(record,null) unless the property pointed to by prop makes sense (aka is part of the type) in the context of the first argument. If it's the same type you can do: let rec getSafeValue (record:'a) (prop: PropertyInfo) = match prop. GetValue(box record, null) with | :?
String as str -> "'" + str + "'" | :? Option as opt -> match opt with | Some v -> getSafeValue v prop | None -> "null" | _ as v -> v.ToString() but if the type of v is derived from 'a it will match the last case so for the above to work they'd need to be exactly the same type.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.