2017-04-01 7 views
1

以下にリストされているすべての機能は、期待通りに機能します。Ocamlでトライを印刷

(最後の1を除く)私は、私はそれがlistchar listsの戻りたいto_list仕事をしようとしてんだけど、私は今のところ、私は戻って、簡単なprintsでそれを実装するだけで、管理unit

type trie = Trie of bool * (char * trie) list 
let empty = Trie (false, []) 

let explode wd = (*breaks up a word in a list of chars*) 
    let rec exp i acc = 
     if i = -1 then acc else exp (i-1) (wd.[i]::acc) in 
     exp (String.length wd - 1) [] 

let insert tr wd = (*insert a word into the trie*) 
let rec insert' wd tr = match wd, tr with 
    | [], Trie (_, l) -> Trie (true, l) 
    | wh::wt, Trie (b, l) -> 
     try Trie(b, (wh, insert' wt (List.assoc wh l))::List.remove_assoc wh l) 
     with Not_found -> Trie (b, (wh, insert' wt empty) :: l) 
     in insert' (explode wd) tr 

let from_list = List.fold_left insert empty (*makes trie from string list*) 

let to_list tr = (*prints all trie words*) 
    let rec to_list' (Trie (b, l)) acc = 
     if b then 
      (
       List.iter print_char (List.rev acc); 
       print_char '\n' 
      ) 
     else(); 
     List.iter (fun (c, t) -> to_list' t (c::acc)) l in 
    to_list' tr [] 

編集:@Goswin von Brederlowに感謝私​​のto_list印刷機能を明確にしました。私が試した何

let to_list tr = (*fails at compile time*) 
    let rec to_list' acc = function 
     | Trie(_, []) -> [List.rev acc] 
     | Trie(true, (c, h)::_) -> (List.rev acc) :: to_list' (c::acc) h 
     | Trie(_, l) -> List.map (fun (c, t) -> to_list' (c::acc) t) in 
     to_list' [] a tr 

例:List.mapのみタイプ'a listはなく任意のn-depth nested listsを返すことができるので、

let t = from_list ["hello"; "hell"; "helsinki"; "here"];; 
# to_list t;; 
here 
helsinki 
hell 
hello 
- : unit =() 

それが失敗していますか?

+1

どのような出力が得られますか、どのようなエラーが発生しますか? charリストのリストは意味をなさない。あなたは文字列のリストを意味しないのですか?そうすれば 'from_list(to_list trie)'が動作します。私は、from_listとto_listが異なるリストタイプを使用しているすべてのモジュールに悩まされます。 –

+1

["hello"、 "hello"、 "hella"]とあなたの '| Trie(true、(c、t):: _) - > 'は動作しません。あなたは '|トライ(真実、私) - >そこに。私はこれを2つに分割することを提案します。最初にtrueをチェックし、単語をアキュムレータに追加し、2番目の子を反復処理します。注意: '| Trie(_、[]) - > 'は意味がありません。 –

+0

@GoswinvonBrederlowこれを指摘してくれてありがとう、私の最初の試みはこの関数の論理を取得することだったので、簡単な 'prints'で試してみたところ、トライのすべての単語をcharのリストとして取得したいのでした。 '文字列のリスト 'を入力して' string'を作成する 'to_string'関数を既に持っています。私はちょうどここにそれを載せたくありませんでした。既にこの質問ではあまりにも多くのコードです。 – Oleg

答えて

1

mapにリストのリストを返してからそれを平坦化するか、アキュムレータをスレッド化する2つの合理的な方法があります。

let to_list trie = 
    let rec recur acc chars (Trie (word_here, entries)) = 
    let acc = 
     match entries with 
     | [] -> acc 
     | _ -> 
     List.fold_left (fun acc (char, trie) -> 
      recur acc (char::chars) trie) 
      acc entries in 
    if word_here then List.rev chars::acc 
    else acc in 
    recur [] [] trie 
1

List.mapはリストのリストを返すことができます。これはあなたの問題ではありません。

あなたのto_list関数はコンパイルされませんが、エラーは表示されません。これにより、アドバイスを提供することが難しくなります。

私はコードで表示される最初の問題はこれです:

List.map (fun (c, t) -> to_list' (c::acc) t) 

ただ一つの引数がここにあります。しかし、一般的には、関数(あなたが持っているもの)とリスト(あなたが持っていないもの)の2つの引数を指定したいと思うでしょう。