2014-11-27 5 views
0

그래서 목록 내에 VarDecl을 포함하는 stmt (대수 유형) 목록이 있습니다. stmt list에서 VarDecl list으로 목록을 축소하고 싶습니다. List.filter을 사용할 때 다른 유형은 모두 제거 할 수 있지만 여전히 stmt list으로 남습니다.OCaml 목록을 하나의 변형으로 필터링

폴딩으로 형식 변경뿐만 아니라 필터링도 할 수 있었지만 일반화하는 방법을 알 수는 없습니다. (프로젝트에서이 패턴이 필요합니다.)

let decls = List.fold_left 
    (fun lst st -> match st with 
     | VarDecl(vd) -> vd :: lst 
     | _ -> lst 
    ) [] stmts in 

필터를 수행하고 목록 유형의 변형에 캐스트하는 더 좋은 방법이 있습니까?

답변

1

type stmt = VarDecl of int | Foo of int | Bar | Fie of string 

같은 유형과 stmt를 목록이 배터리는 당신이 당신이받을거야만큼이나 간결 생각

let vardecl_ints l = 
    List.filter_map (function Vardecl i -> Some i | _ -> None) l 

let foo_ints l = 
    List.filter_map (function Foo i -> Some i | _ -> None) l 

을 수행 할 수 있습니다. do not는 ADT의 일반적인 "list-getters"를 만들 수 있다고 생각합니다.당신이 의존성을 원하지 않는 경우
let bars l = 
    List.filter_map (function Bar -> Some Bar | _ -> None) l 

https://github.com/ocaml-batteries-team/batteries-included/blob/master/src/batList.mlv#L456

는 filter_map의 배터리 구현을 가지고있다. Acc 대신에 []가있는 기능 버전은 매우 유사 할 것이며, (x :: dst)과 끝에 |>List.rev만을 수행합니다.

0

형식 정의 (또는 단순화 된 버전)를 보지 않고도 대답하기가 어렵습니다.

참고하지만,이 정의가있는 경우 있음 :

type xyz = X | Y | Z 

값의 X, Y, Z는 유형이 없습니다. 그것들은 가치입니다. 아마도 Vardecl도 가치가 있습니다. 그래서 당신은 OCaml에서 그 타입의리스트를 가질 수 없습니다.

는 업데이트 나는이 같은 경우에 대해 수행 한

한 가지가 하나의 변형에서 투사 유형을 사용하는 것입니다은 당신이 원하는 :

type xyz = X | Y of int * int | Z 
val extract_proj : xyz -> (int * int) list -> (int * int) list = <fun> 
val filter_to_y : xyz list -> (int * int) list = <fun> 
# filter_to_y [X; Z; Y(3,4); Z; Y(4,5)];; 
- : (int * int) list = [(3, 4); (4, 5)] 
:

여기
type xyz = X | Y of int * int | Z 

let extract_proj v l = 
    match v with 
    | X | Z -> l 
    | Y (a, b) -> (a, b) :: l 

let filter_to_y l = 
    List.fold_right extract_proj l [] 

는 최상위 세션의

+0

죄송합니다. 더 구체적으로 설명해야합니다. 인수 목록은 변형 그룹의 그룹이며 하나의 변형으로 축소하려고합니다. –

+0

변형이 하나뿐이라면 형식은 여전히 ​​'stmt list'입니다. 유형을 변경하지 않으며, 이는 사용자가 요청하는 것처럼 들립니다. –

1

GADT 또는 다형성 변형을 사용할 수 있지만 둘 다 복잡성을 높이는 경향이 있습니다.

여기 다형 변종이 문제를 접근하는 방법의 대략적인 스케치는 다음과 같습니다

type constant = [ `Int of int | `String of string ] 
type var = [ `Var of string ] 
type term = [ constant | var | `Add of term * term ] 

let rec select_vars (list : term list) : var list = 
    match list with 
    | [] -> [] 
    | (#var as v)::list -> v::select_vars list 
    | _::list -> select_vars list 

let rec select_constants (list : term list) : constant list = 
    match list with 
    | [] -> [] 
    | (#constant as k)::list -> k::select_constants list 
    | _::list -> select_constants list 

또 다른 가능성은 밖으로 당신 이 목록을 가질 수있는 명시 적 유형으로 var의 비트를 당겨하는 것입니다 :

type var = { 
    ... 
} 

type term = 
    | Int of int 
    | Var of var 

이 비트 그냥 생성자 인수 할 필요 이상의 오버 헤드를 가지고, 당신은 가능성이 필요합니다 있도록 varterm 아니다 랩핑과 언 래핑을 할 수 있습니다. 당신을 가정

관련 문제