4 people like it.

Recursive active pattern for expanding list quotations

This is a recursive active pattern for extracting the elements of a list quotation as a list of Exprs, There doesn't seem to be a List pattern in the standard library. The compiler will complain about this recursive pattern unless you use #nowarn "40".

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
open FSharp.Reflection
open FSharp.Quotations
open FSharp.Quotations.Patterns

let rec (|List|_|) =
        let isListType (u:UnionCaseInfo) = u.DeclaringType.IsGenericType && u.DeclaringType.GetGenericTypeDefinition() = typedefof<list<_>>
        function
        | NewUnionCase(uci, []) when isListType uci -> Some []
        | NewUnionCase(uci, lhs::(NewUnionCase(_, []))::[]) when isListType uci  -> Some (lhs::[])
        | NewUnionCase(uci, lhs::List(rhs)::[]) when isListType uci  -> Some (lhs::rhs)
        | _ -> None

// Usage
match <@[5.;6.;7.;8.]@> with
| List e -> printf "%A" e
| _ -> ()

match <@[[5.;6.;7.];[8.]]@> with
| List e -> e |> List.map (function |List ee-> printf "%A" ee | _ ->())
| _ -> []
namespace Microsoft.FSharp
namespace Microsoft.FSharp.Reflection
namespace Microsoft.FSharp.Quotations
module Patterns

from Microsoft.FSharp.Quotations
Multiple items
module List

from Microsoft.FSharp.Collections

--------------------
type List<'T> =
  | ( [] )
  | ( :: ) of Head: 'T * Tail: 'T list
    interface IReadOnlyList<'T>
    interface IReadOnlyCollection<'T>
    interface IEnumerable
    interface IEnumerable<'T>
    member GetReverseIndex : rank:int * offset:int -> int
    member GetSlice : startIndex:int option * endIndex:int option -> 'T list
    member Head : 'T
    member IsEmpty : bool
    member Item : index:int -> 'T with get
    member Length : int
    ...
val isListType : (UnionCaseInfo -> bool)
val u : UnionCaseInfo
type UnionCaseInfo =
  member GetCustomAttributes : unit -> obj []
  member GetCustomAttributes : attributeType:Type -> obj []
  member GetCustomAttributesData : unit -> IList<CustomAttributeData>
  member GetFields : unit -> PropertyInfo []
  member DeclaringType : Type
  member Name : string
  member Tag : int
property UnionCaseInfo.DeclaringType: System.Type with get
property System.Type.IsGenericType: bool with get
System.Type.GetGenericTypeDefinition() : System.Type
val typedefof<'T> : System.Type
type 'T list = List<'T>
active recognizer NewUnionCase: Expr -> (UnionCaseInfo * Expr list) option
val uci : UnionCaseInfo
union case Option.Some: Value: 'T -> Option<'T>
val lhs : Expr
Multiple items
active recognizer List: Expr -> Expr list option

--------------------
module List

from Microsoft.FSharp.Collections

--------------------
type List<'T> =
  | ( [] )
  | ( :: ) of Head: 'T * Tail: 'T list
    interface IReadOnlyList<'T>
    interface IReadOnlyCollection<'T>
    interface IEnumerable
    interface IEnumerable<'T>
    member GetReverseIndex : rank:int * offset:int -> int
    member GetSlice : startIndex:int option * endIndex:int option -> 'T list
    member Head : 'T
    member IsEmpty : bool
    member Item : index:int -> 'T with get
    member Length : int
    ...
val rhs : Expr list
union case Option.None: Option<'T>
val e : Expr list
val printf : format:Printf.TextWriterFormat<'T> -> 'T
val map : mapping:('T -> 'U) -> list:'T list -> 'U list
val ee : Expr list

More information

Link:http://fssnip.net/82f
Posted:3 years ago
Author:allisterb
Tags: #active patterns , list , quotations