2016-11-02 16 views
2

だろうが、実装に基づいて、すべての順列を生成するための簡単なコードでは、ここで見つける:All permutations of a listのF# - 結果の型は、ここで無限のエラー

let concatElement element sequence = 
    seq { 
     yield element 
     yield! sequence 
    } 

let rec permute (choices : 'a seq)= 
    seq { 
     if Seq.isEmpty choices then 
      yield Seq.empty 
     else 
      for choice in choices do 
       let remaining = choices |> Seq.where (fun el -> el <> choice) 
       yield concatElement choice (permute remaining) 
    } 

私はコンパイル時にエラーが発生します「結果の型は次のようになり'a'と 'seq <' a> 'を統一すると無限になります"yield concatElement choice (permute remaining)"

ここで何が間違っていますか?

+2

返品の種類は何ですか? 'seq >'であると仮定すると、最後の行の 'concatElement'の最初の引数は' seq <'a> 'になる必要がありますが、 'choice'は' a'です。 – Lee

+0

concatElementはシーケンスに1つの要素を追加し、シーケンス<'a>を返します。したがって、yield concatElementはseq <'a>を生成し、結果としてseq >が生成されます。私は何が欠けていますか?または、私は "頭"を渡し、2つのシーケンスを連結する必要がありますか? –

+3

'permute'が' seq > 'を返した場合、' concatElement choice(permute remaining) 'はタイプエラーである' 'a'と' seq 'を連結しようとしています。 'permute'に明示的な戻り値の型を追加すると、より有用なエラーメッセージが出る可能性があります。 – Lee

答えて

4

'a seqのシーケンスの1つの要素として、yield'a seqにしようとしています。そのためには、'a'a seqと同じタイプでなければなりません。したがって、タイプは「無限」です。無限に入れ子にする必要があります。

私は、あなたが何らかの形でシーケンス要素をループする必要があることを認識していることが分かりました。あなたが持っているように、for .. inの構文を使って反復することができます。あるいはF#は実際にこれを行うyield!演算子を提供します。この精神で、あなたの答えは

let rec permute (choices : 'a seq) (permBuilder: 'a seq) : seq<seq<'a>>= seq { 
    if Seq.isEmpty choices then 
     yield permBuilder 
    else 
     for choice in choices do 
      let remaining = choices |> Seq.where (fun el -> el <> choice) 
      let newBuilder = concatElement choice permBuilder 
      yield! permute remaining newBuilder } 

あるいは、その代わりに、私たちは私たちのために(!系列の)自動的に配列の配列を収集するためにSeq.collect機能を使用することができ、私たちは素敵な機能が残っているように記述することができ明示的なイテレータとスタイルコード:考慮すべき

let prepend element sequence = seq { yield element; yield! sequence } 

let rec permute input = 
    if Seq.length input <= 1 then Seq.singleton input 
    else 
     let without element = Seq.where ((<>) element) input 
     let permutations element = permute (without element) |> Seq.map (prepend element) 
     Seq.collect permutations input 

何かが、しかし:あなたが明瞭でない2つの要素を持っている場合はどうなりますか?たとえば、[1; 1; 2]の順列を取得しようとするとどうなりますか?現在の方法ではこれをうまく処理できません。たとえあなたがwithoutのクロージャを改善したとしても、重複した回答が得られます。

1

私はLee'veがコメントしたように、私はそれを

let concatElement element sequence = 
    seq { 
     yield element 
     yield! sequence 
    } 

let rec permute (choices : 'a seq) (permBuilder: 'a seq) : seq<seq<'a>>= 
    seq { 
     if Seq.isEmpty choices then 
      yield permBuilder 
     else 
      for choice in choices do 
       let remaining = choices |> Seq.where (fun el -> el <> choice) 
       let newBuilder = concatElement choice permBuilder 
       for perm in permute remaining newBuilder do 
        yield perm 

だと思う、私は>> '配列<配列<で>' 配列<をCONCATしようとしました。私のコードは順列よりもループがありませんでした。

関連する問題