[OCaml] преобразование структуры данных в строку

 
0
 
Functional languages
ava
Kakadu | 22.09.2009, 21:30


type logConst = True | False;;
type subjVal = SubjVal of string * bool | LogConst;;
type predicateName = PredicateName of string;;
    
type term = subjVal;;
type atomFormula = AtomFormula of predicateName * term list;;
type fip = Formula of atomFormula |  LogConst of logConst
        | BinOp of string*fip*fip;;

let t2 = BinOp ( "AND",
                 LogConst True,
                 Formula (AtomFormula (PredicateName ("P"), [ SubjVal ("a", true) ] ) ) 
                );;

let term_to_string (t:term) : string = ""
    ;;
let string_of_atomformula (af:atomFormula) =
    let ans = ref "" in
        let terms_to_string tlst =
            List.iter (fun t -> ans := (!ans ^ ","^ (term_to_string t) )) tlst
                  
            in
            terms_to_string (    match af with
                                | AtomFormula (name,lst) -> lst
                );
            "AtomFormula(\""^(    match af with
                                | AtomFormula (name,lst) -> (match name with
                                                            |  PredicateName n -> n )
                ) ^"\"" ^ !ans ^ ")"
    ;;
    
let rec string_of_fip f =
    match f with
        | Formula af -> "Formula( " ^ (string_of_atomformula af) ^ " )"
        | LogConst lc -> ( 
                match lc with
                    | True -> "True"
                    | False -> "False"
            )
        | BinOp (name,fip1,fip2) ->
            " ("^(string_of_fip fip1)^ " "^name^" "^(string_of_fip fip2)^") " 
    ;;

Функция string_of_atomformula это какой-то трэш. smile  Как это правильно писать?
Comments (2)
ava
Void | 22.09.2009, 21:33 #
Что ж, взглянем на эту функцию. Первое, что бросается в глаза, — это деструктивное, с присваиваниями, построение строки. Вообще, в OCaml это нормально, но в данном случае никакого выигрыша не даёт (для инкрементального построения строк надо использовать Buffer). Поэтому перепишем terms_to_string в чистом виде с использованием стандартной функции fold_left. Вообще, если из списка нам нужно сделать одно значение, это почти всегда указывает на применимость свёртки (fold).
let terms_to_string = function
    | [] -> ""
    | t::ts -> List.fold_left (fun s x -> s ^ ", " ^ term_to_string x) (term_to_string t) ts

К функции явно напрашивается обобщение: списки, разделённые запятыми, можно много из чего строить. Параметризуем её функцией перевода элемента списка в строку:
let comma_separated_list tostr = function
    | [] -> ""
    | t::ts -> List.fold_left (fun s x -> s ^ ", " ^ tostr x) (tostr t) ts

Стоит обратить внимание на получившийся тип:
val comma_separated_list : ('a -> string) -> 'a list -> string

Если вдруг эта функция станет узким местом, можно переписать с помощью Buffer:
let comma_separated_list tostr = function
    | [] -> ""
    | t::ts ->
        let b = Buffer.create 10 in
        Buffer.add_string b (tostr t);
        List.iter (fun x ->
                Buffer.add_string b ", ";
                Buffer.add_string b (tostr x))
            ts;
        Buffer.contents b

Теперь terms_to_string можно записать очень просто:
let terms_to_string = comma_separated_list term_to_string (* карринг *)

Ну и наконец сама функция string_of_atomformula:
let string_of_atomformula = function
    | AtomFormula(PredicateName name, terms) ->
        "AtomFormula(\"" ^ name ^ "\"" ^ terms_to_string terms ^ ")"


P.S. Темы всё-таки корректнее называть надо.
ava
Kakadu | 05.10.2009, 20:42 #
Да. я наконец-то собрался и осмыслил это. спасибо
Please register or login to write.
Firm of day
Вы также можете добавить свою фирму в каталог IT-фирм, и публиковать статьи, новости, вакансии и другую информацию от имени фирмы.
Подробнее
Contributors
  Void   Kakadu
advanced
Submit