Polymorphic variants question
[
Home
]
[ Index:
by date

by threads
]
[ Message by date: previous  next ] [ Message in thread: previous  next ] [ Thread: previous  next ]
[ Message by date: previous  next ] [ Message in thread: previous  next ] [ Thread: previous  next ]
Date:  20060901 (19:30) 
From:  skaller <skaller@u...> 
Subject:  Re: [Camllist] Polymorphic variants question 
On Fri, 20060901 at 18:31 +0100, David Allsopp wrote: > let f x = if x = `A then (true, `B) else (false, x) > let (f : [`A  `C] > bool * [`A  `B  `C]) = fun x > ... BTW: when using polymorphic variants I find it is a good idea to: (a) provide names (aliases, abbreviations) for your types. (b) annotate function arguments and returns  if not all of them, focus on the top level ones: it's necessary for the mli file anyhow. (c) Prefer let f x = match x with  ... over let f = fun x > ... and let f = function  .. and in particular for big top level functions like let f (x:t1):t2 = print_endline ("In Debug " ^ string_of_t1 x); let r : t2 = match x with .. in print_endline ("Out Debug " ^ string_of_t2 r); r This shape instruments the input type, output type, input value and output value. The thing about polymorphic variants is that because (a) the typing is structural not nominal (like ordinary variants) (b) type inference tries to figure out the types from usage scattered through the program it is not only easy to extend them .. it is easy to extend them incorrectly .. and the diagnostics from big variants are horrible :) Using annotations tends to localise the errors and give you more information, including Ocaml's smart trick of using your own alias. (This is very clever :) It also often reports that you're missing a particular constructor. I've been using PM variants for a while now. I just converted a couple of nonPM ones over. I kind of like this function, it prints many of the types I use in my compiler in one function, almost like overloading :) let string_of_term dfns term = match term with  #qualified_name_t as x > string_of_qualified_name x  #regexp_t as x > string_of_re x  #typecode_t as x > string_of_typecode x  #tpattern_t as x > string_of_tpattern x  #literal_t as x > string_of_literal x  #expr_t as x > string_of_expr x  #pattern_t as x > string_of_pattern x  #statement_t as x > string_of_statement 0 x  #exe_t as x > string_of_exe 0 x  #btypecode_t as x > string_of_btypecode dfns x (* hack .. the type because tbexpr_t is a pair not a variant *)  #bexpr_t as x > string_of_bound_expression dfns (x,`BTYP_void)  #bexe_t as x > string_of_bexe dfns 0 x  #ast_term_t as x > string_of_ast_term 0 x (* hack cause we don't know the name *)  #symbol_definition_t as x > string_of_symdef x "unk" []  #bbdcl_t as x > string_of_bbdcl dfns x 0  #param_kind_t as x > string_of_param_kind x  #property_t as x > string_of_property x  #c_t as x > string_of_code_spec x  #dcl_t as x > string_of_dcl 0 "unk" (Some 0) [] x  #asm_t as x > string_of_asm 0 x  #iface_t as x > string_of_iface 0 x  #access_t as x > string_of_access x  #biface_t as x > string_of_biface dfns 0 x  #btype_qual_t as x > string_of_bqual dfns x  #type_qual_t as x > string_of_qual x  #requirement_t as x > string_of_raw_req x  #ikind_t as x > string_of_ikind x  #named_req_expr_t as x > string_of_named_req_expr x  #raw_req_expr_t as x > string_of_raw_req_expr x  #glr_term_t as x > string_of_glr_term x let st dfns term = string_of_term dfns term This function doesn't DO anything I couldn't already do. It just saves me worrying what the type of the term is, and then trying to remember the name of the function that prints it. The PM variants let me unify any variants types I'm using, which is why I converted most of the remaining nonPM variants over. Stick with them .. they're worth it!  John Skaller <skaller at users dot sf dot net> Felix, successor to C++: http://felix.sf.net