F# and negative match

眉间皱痕 提交于 2019-12-10 10:48:35

问题


I have a discriminated type:

type Item =
    | Normal of string * float32
    | Special1 of Item
    | Special2 of Item

And I have a function using this type:

let rec calcItem (i: Item ) =
    match i with
    | Normal(_, p) -> p
    | Special1(g) | Special2(g) -> (calcItem g) + 1

In my case, the Special_n types will be defined in the same form. So I am wondering if it is possible to use wildcard pattern to match all these types. The _ match does not work, because it does not accept arguments.


回答1:


Similar to this one and this one.

As explained there you can use reflection or redesign your DU (this is what I would recommend).

Reflection:

open Microsoft.FSharp.Reflection

type Item =
    | Normal of string * float32
    | Special1 of Item
    | Special2 of Item

let innerValue a =
    FSharpValue.GetUnionFields (a, a.GetType())
    |> snd
    |> Seq.head
    :?> Item

let rec calcItem (i: Item ) =
    match i with
    | Normal (_, p) -> p
    | specialN      -> calcItem (innerValue specialN) + 1.0f

Redesign the DU:

type Item =
    | Normal of string * float32
    | Special of int * Item

let rec calcItem (i: Item ) =
    match i with
    | Normal  (_, p) -> p
    | Special (_, g) -> calcItem g + 1.0f



回答2:


You can try with active pattern:

type Item =
    | Normal of string * float32
    | Special1 of Item
    | Special2 of Item

let (|Special|Norm|) (item) =
    match item with
    | Special1(g) | Special2(g) -> Special(g)
    | _ -> Norm

let rec calcItem (i: Item ) =
    match i with
    | Normal(_, p) -> p
    | Special(g) -> (calcItem g) + 1.0f

This does not completely remove the need of matching each SpecialN case, but it separates it from the calcItem function



来源:https://stackoverflow.com/questions/24137032/f-and-negative-match

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!