如何在F#中检索元组的头部和尾部

M-A*_*man 0 f# tuples

  1. 如何在F#中检索元组的头部和尾部?

    例如Conj (a, b),头部是Conj,尾部是(a, b).

  2. 我想buildtree在每个参数上递归运行函数,把头作为Node元素,F#中的映射在哪里?

    let rec getparams = map List.head (List.tail getparams);
    
    type Elem = Prop
    type Tree = E | T of Elem * Tree * Tree
    
    let rec buildtree vars = function
        | E = head vars
        | T = buildtree (getparams vars)
    
    Run Code Online (Sandbox Code Playgroud)

更新后:

open System
open Microsoft.FSharp.Reflection
// Learn more about F# at http://fsharp.net
//type Prop = {a: string; b: string}
//let Prop a b = (a, b) 
type Op = Prop
type tree = E | T of Op * tree * tree
let tree x y z = (x, y, z)

type binOp = Conj | Disj | Impl 
type expr =   
| Prop of string   
| BinOp of binOp * expr * expr 
| Conj of expr * expr
| Disj of expr * expr
| Impl of expr * expr

type Prop = {a: string}
let Prop a = (a)

//type Conj = {a : Prop; b : Prop} 
let Conj a b = (a, b)

//type Conj_Int = {a : Prop; b : Prop} 
let Conj_Int a b = Conj a b
//type Conj_Elmin1 = {a : Conj}
let Conj_Elmin1 a = fst a
//type Conj_Elmin2 = {a : Conj}
let Conj_Elmin2 a = snd a

//type Impl = {a : Prop; b : Prop} 
let Impl a b = (a b)
//type Impl_Int = {assume : Prop; b : Prop} 
let Impl_Int assume b = Impl assume b
//type Impl_Elmin = {a :string; b : Impl}
let Impl_Elmin a b = if a = fst b then snd b

type Neg = {a : Prop;}
let Neg a = (a)

//type Double_Neg_Int = {a : Prop;}
let Double_Neg_Int a = Neg(Neg(a))

//type Double_Neg_Elmin = {a : Prop}
let Double_Neg_Elmin a = fst(fst(a))

//type Disj = {a : Prop; b : Prop} 
let Disj a b = (a,b)

//type Disj_Int1 = {a : Prop; b : Prop} 
let Disj_Int1 a b = (a b)
//type Disj_Int2 = {a : Prop; b : Prop} 
let Disj_Int2 a b = (a b)

//type Disj_Elmin1 = {a : Disj}
let Disj_Elmin1 a = fst(a)
//type Disj_Elmin2 = {a : Disj}
let Disj_Elmin2 a = snd(a)

type TupleSplitter = static member splitTuple (a,b,c) = (a,(b,c)) 

let tupleToList t = if Microsoft.FSharp.Reflection.FSharpType.IsTuple(t.GetType()) then Some (Microsoft.FSharp.Reflection.FSharpValue.GetTupleFields t |> Array.toList) else None
    let operation x = List.head(List.ofSeq(FSharpValue.GetTupleFields(x)))
let parameters x = List.tail(List.ofSeq(FSharpValue.GetTupleFields(x)))


let rec map f = function | Prop _ as t -> f t | BinOp(op, a, b) -> f(BinOp(op, map f a, map f b))
(*
let rec map f = function   
| Prop _ as t -> f t   | Conj(a, b) -> f(Conj(map f a, map f b))   
| Disj(a, b) -> f(Disj(map f a, map f b))   
| Impl(a, b) -> f(Impl(map f a, map f b)) 
*)
let buildtree vars expr = map (function Prop v -> Map.find v vars | expr -> expr) expr 

let t = buildtree(Conj("a","b"))
Run Code Online (Sandbox Code Playgroud)
  1. 如何有两种类型的表达式Op*Tree*Tree和Op*Tree?

Tom*_*cek 5

正如Ankur所说,你不能得到一个元组的头和尾 - 这些操作是为处理具有任意长度的函数列表而设计的,并且无法定义在编译时具有已知长度的元组.如果你想要任意长度的数据,你应该使用元组和模式匹配(或List.headList.tail).

如果您确实需要动态处理元组,可以使用F#反射:

open Microsoft.FSharp.Reflection

(1,2,3)
|> FSharpValue.GetTupleFields // Get fields of tuple as an array
|> List.ofSeq                 // Convert array to a list
|> List.tail                  // Now you can process list using head/tail
Run Code Online (Sandbox Code Playgroud)

但请注意,反射通常有点慢,只应在需要时使用(即编写一些动态且无法以其他方式编写的代码).