F#模式匹配(按类型) [英] F# Pattern-matching by type

查看:64
本文介绍了F#模式匹配(按类型)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

F#中按参数类型进行模式匹配的方式如何?

How pattern-matching by type of argument works in F#?

例如,我正在尝试编写一个简单的程序,如果提供 number ,它将计算平方根,否则返回它的参数.

For example I'm trying to write simple program which would calculate square root if number provided or return it's argument otherwise.

open System

let my_sqrt x =
  match x with
  | :? float as f -> sqrt f
  | _ -> x


printfn "Enter x"
let x = Console.ReadLine()

printfn "For x = %A result is %A" x (my_sqrt x)

Console.ReadLine()

我收到此错误:

error FS0008: This runtime coercion or type test from type
    'a    
 to 
    float    
involves an indeterminate type based on information prior 
to this program point. Runtime type tests are not allowed
on some types. Further type annotations are needed.

因为 sqrt float 一起工作,所以我检查了 float 类型,但是猜测可能会有更好的解决方案-例如检查输入是否为数字(通常),如果是,则将其强制转换为浮点数?

Since sqrt works with float I check for float type, but guess there could be better solution - like check if input is number (in general) and if so, cast it to float?

推荐答案

这里的问题是 x 的类型实际上是 string .加上来自 Console.ReadLine 的信息,该字符串中存储的信息类型只能在运行时确定.这意味着您既不能使用模式匹配,也不能在强制模式下使用模式匹配.

The problem here is that the type of x is actually a string. Adding that it comes from Console.ReadLine, what kind of information is stored in that string is only possible to determine at runtime. This means that you can't use neither pattern matching, nor pattern matching with coercion here.

但是您可以使用活动模式.因为实际的数据存储在 x 中只有在运行时才知道,所以您必须解析该字符串并查看包含的内容.

But you can use Active Patterns. As what actual data is stored in x is only known at runtime, you have to parse the string and see what is contains.

因此,假设您期望的是 float ,但是由于用户可以输入所需的内容,因此无法确定.我们将尝试解析我们的字符串:

So suppose you are expecting a float, but you can't be sure since user can input whatever they want. We are going to try and parse our string:

let my_sqrt x =
    let success, v = System.Single.TryParse x // the float in F# is represented by System.Single in .NET
    if success then sqrt v
    else x

但这不会编译:

预计该表达式的类型为float32,但此处的类型为字符串

This expression was expected to have type float32 but here has type string

问题在于,编译器根据表达式 sqrt(System.Single.Parse(x))推断函数返回 float32 .但是,如果 x 没有解析为浮点数,我们打算将其返回,并且由于 x 是一个字符串,因此我们在这里存在不一致之处.

The problem is that the compiler inferred the function to return a float32, based on the expression sqrt (System.Single.Parse(x)). But then if the x doesn't parse to float, we intend to just return it, and as x is a string we have an inconsistency here.

要解决此问题,我们将必须将 sqrt 的结果转换为字符串:

To fix this, we will have to convert the result of sqrt to a string:

let my_sqrt x =
    let success, v = System.Single.TryParse x
    if success then (sqrt v).ToString()
    else x

好的,这应该可以,但是它不使用模式匹配.因此,让我们定义活动"模式,因为我们不能在此处使用常规模式匹配:

Ok, this should work, but it doesn't use pattern matching. So let's define our "active" pattern, since we can't use regular pattern matching here:

let (|Float|_|) input =
    match System.Single.TryParse input with
    | true, v -> Some v
    | _ -> None

基本上,仅当 input 可以正确地解析为浮点文字时,此模式才会匹配.在初始函数实现中可以使用它的方式如下:

Basically, this pattern will match only if the input can be correctly parsed as a floating point literal. Here's how it can be used in your initial function implementation:

let my_sqrt' x =
    match x with
    | Float f -> (sqrt f).ToString()
    | _ -> x

这看起来很像您的函数,但是请注意,我仍然必须添加 .ToString()位.

This looks a lot like your function, but note that I still had to add the .ToString() bit.

希望这会有所帮助.

这篇关于F#模式匹配(按类型)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆