F# Pattern-matching by type -
how pattern-matching type of argument works in f#?
for example i'm trying write simple program calculate square root if number provided or return it's argument otherwise.
open system let my_sqrt x = match x | :? float f -> sqrt f | _ -> x printfn "enter x" let x = console.readline() printfn "for x = %a result %a" x (my_sqrt x) console.readline()
i error:
error fs0008: runtime coercion or type test type 'a float involves indeterminate type based on information prior program point. runtime type tests not allowed on types. further type annotations needed.
since sqrt
works float
check float
type, guess there better solution - check if input number (in general) , if so, cast float?
the problem here type of x
string
. adding comes console.readline
, kind of information stored in string possible determine @ runtime. means can't use neither pattern matching, nor pattern matching coercion here.
but can use active patterns. actual data stored in x
known @ runtime, have parse string , see contains.
so suppose expecting float
, can't sure since user can input whatever want. going try , parse our string:
let my_sqrt x = let success, v = system.single.tryparse x // float in f# represented system.single in .net if success sqrt v else x
but won't compile:
this expression expected have type float32 here has type string
the problem compiler inferred function return float32
, based on expression sqrt (system.single.parse(x))
. if x
doesn't parse float, intend return it, , x
string have inconsistency here.
to fix this, have convert result of sqrt
string:
let my_sqrt x = let success, v = system.single.tryparse x if success (sqrt v).tostring() else x
ok, should work, doesn't use pattern matching. let's define our "active" pattern, since can't use regular pattern matching here:
let (|float|_|) input = match system.single.tryparse input | true, v -> v | _ -> none
basically, pattern match if input
can correctly parsed floating point literal. here's how can used in initial function implementation:
let my_sqrt' x = match x | float f -> (sqrt f).tostring() | _ -> x
this looks lot function, note still had add .tostring()
bit.
hope helps.
Comments
Post a Comment