2016-08-11 5 views
1

タイプエイリアスがどのように機能するのか、そして拡張子によって、type Set = Int => Booleanでモデル化された単純なSetタイプが部分的な機能を持つクラスとして書き直される方法を理解しようとしています。部分関数を使用してScalaのSetモデルを作成します。タイプエイリアス:Set = Int => Boolean

背景:

type Set = Int => Boolean 
def union(s: Set, t: Set): Set = (x => s(x) || t(x)) 
def contains(s: Set, n: Int): Boolean = s(n) 
val s1 = Set(3) 
val s2 = Set(7) 
val u1 = union(s1, s2) 
contains(u1, 3)    // res4: Boolean = true 

すべてが順調と良い:私は上記のようなタイプのエイリアスを作成し、シンプルな機能セットのデータ型として使用できることを理解しています。いくつかの考えを取るが、私はそれがどのように機能するかを知る。私は、私の最初の試みは、このようなものになるだろうクラスにこれを有効にしたいのであれば

union(s: (Int => Boolean), t: (Int => Boolean)): Int => Boolean 

u1 は、本質的に基づいて、部分関数となる

case class Set(v: Int) { 
    def apply(i: Int) = i == v 
    def contains(n: Int): Boolean = this(n) 
    def union(n: Set): Set = (x => n(x) || apply(x)) // Missing param 
} 

しかし、それは動作しません。 (unionの定義にはコンパイルエラーがあり、xはパラメータがありません)。

これをしばらくお待ちいただいた後、実際にコレクションベースのSetクラスを作成するなどの、もっと不可欠な方法に頼らなくても、同様の型を実装する方法については困惑しています。純粋に機能的な方法でこれを行う方法が必要です。

+1

OOに頼らずに、あなたが望むものを達成する方法はありません。 'union 'の問題はSetでなければならないということですが、それは関数として定義されています。これをSetにするためには、Setを拡張したインスタンスを用意する必要があります.setを適用すると、関数を基にした実装のポイントをほぼ破棄します。 – pedrofurla

+0

種類のエイリアスは置換だけで動作します。 – pedrofurla

+0

あなたのスコープ内に3つのSet定義があると思います... xD 1.タイプ別名 'Set'(関数)、2. val s1 = Set(3)(' scala.Set')3.あなたの 'ケースクラスSet'を生成する。それはうまくいきません...そして、いいえ、組合は部分的な機能ではありません。 –

答えて

1

Intではなく、Int => Booleanをラップする必要があります。だから、

Setの独自の定義について
case class Set(f: Int => Boolean) { 
    def apply(i: Int) = f(i) 
    def union(s: Set) = Set(x => this(x) || s(x)) 
    // or Set(union(f, s.f)) to use existing definition of union 
} 

applyは単一要素のセットになり、あなたがunionを定義することはできません驚くべきことではない:2つの要素の集合の和集合は、複数の要素を持つことができます。

スカラには値と型の名前空間が別々にあります。 val Setobject Set又はvar Set値を定義し、case classの両方を画定するtype Setまたはclass Setは、唯一タイプSetを定義します。今、Set(3)は、Setと呼ばれます。最初のコードサンプルにはそのような値がないため、自動的にインポートされるscala.Predefのものを使用します。 scala.Predef.Set(3)は、に拡張され、union(s1, s2)がコンパイルされる理由で、scala.collection.Set[Int]を返します。 case classは、タイプの両方を値として定義します。したがって、上記のコードでは、scala.Predef.Setの代わりにこの値が使用されるため、Set(3)はコンパイルされません。

+0

これは非常に面白いです。 'Int => Boolean'をラップすることは考えていませんでしたが、望ましいエンドポイントには達しません。これは、型エイリアスベースのAPIに似たAPIです。つまり、例えば、val s1 = Set(3)とs1.union(s2)を実行できることです。 – Zac

+0

'val s1 = Set(3)'と書いておきたい場合は、 'object set'に' def apply(i:Int) 'を定義するだけです。コードの最初の部分で 'Set(3)'はあなたが定義したものではなく 'scala.collection.Set'を使用しています! 'union'は標準の' Set [A] 'が' A => Boolean'を拡張しているためにのみ機能します。 –

+0

私は詳細な説明を追加しました。 –

関連する問題