6

Scala で代数データ型を使用して Sql の一部を記述しようとしているときに、データ型を表すルート トレイトのサブトレイトを作成する必要があることに気付きました。この要件を満たすと、Haskell の ADT で表現できるかどうかわからないコードが生成されます。また、Haskell とは異なり、ADT は Scala のネイティブ コンストラクトではないため、次のように考えています。

  1. Haskellでコンストラクターを持つSql「サブタイプ」を持つ型などのモデルを表現することは不可能であるというのは正しいですか? (これが関係しているようです)。StatementSelect
  2. もしそうなら、「ADT」という用語は私が作成したコードに適用できますか?
  3. もしそうなら、Scala はその点で Haskell よりも実際に強力ですか?
  4. そうでない場合、この機能が Haskell に実装されていない理由は何ですか? 自分のモデルで物事を複雑にしすぎているのではないかと考えさせられます

これが私が話しているモデルです:

sealed trait Sql


sealed trait Statement 
  extends Sql

sealed case class Union 
  ( left : Statement, 
    right : Statement ) 
  extends Statement

sealed case class Select
  ( /** other fields don't matter **/
    where : Where )
  extends Statement


sealed trait Where 
  extends Sql

sealed case class And
  ( left : Where,
    right : Where )
  extends Where

sealed case class Or
  ( left : Where,
    right : Where )
  extends Where

sealed case class Equals
  ( /** fields don't matter **/ )
  extends Where
4

3 に答える 3

10

1.いいえ、ルート トレイトが封印されているため、提示された階層を ADT として表すことができます。

data Sql = Statement Statement | Where Where
        --           ^ This is the *type* called `Statement`
        -- ^ This is the *constructor* called `Statement`

data Statement = Union Statement Statement | Select Where

data Where = And Where Where | Or Where Where | Equals

この場合、データ型のすべての「サブクラス」を列挙できるため (Sqlこの場合)、ADT コンストラクターに変換できるため可能です。「コンストラクター」/「サブクラス」をユーザーが任意に追加できるようにする場合にのみ、型階層を ADT としてエミュレートすることは困難です。

2. Scala には言語に ADT がないため、ADT という用語は Scala コードには適用されません。ただし、提示されたクラスはADTと同様に動作するため、「十分に近い」と言えます。

3 & 4.言語にはさまざまな長所と短所があります。

Haskell はすべての Scala 言語機能をエミュレートでき、Scala はすべての Haskell 機能をエミュレートできます。これは、両方の言語が完全にチューリングされており、さまざまなレベルのメタプログラミングが可能であるためです。もちろん、Haskell には Template Haskell があり、何でもエミュレートできます。おそらく TH を使用して、Haskell ファイルに Scala コードを記述し、それを Haskell としてコンパイルすることができます。

オブジェクトと継承は Haskell では必要なく、ADT は Scala ではほとんど必要ないため、この 2 つを比較する理由はありません。ほとんどのオブジェクト指向機能は、単純な Haskell 型クラスとデータ型、およびモジュール境界を使用してエミュレートすることもできます。ADT はケース クラスを使用して Scala でエミュレートでき、Haskell 型クラスは暗黙のパラメーターと暗黙のオブジェクト インスタンスを使用してエミュレートできます。

ただし、Haskell では Scala よりも多くの「暗黙的な言語拡張」が可能であるため、特定の Scala 機能を Haskell でエミュレートする方が一般的には簡単だと思います。つまりMonad、Scala で Haskell をエミュレートしたい場合は、s を使用する部分に多くのコードを記述する必要がありますが、Monadエミュレートしたい場合は、たとえば、Haskell で Scala の区切られた継続または暗黙のパラメーターをエミュレートする必要があります。 、あなたは単に書くことができますMonadインスタンス (継続の場合) またはマルチパラメーター型クラス (暗黙のパラメーターの場合) を 1 回使用すると、実際の関数で後で記述するコードは、ボイラー プレートがほとんどない Scala コードに非常によく似たものになります。Scala の高度な機能のほとんどではないにしても、多くは Haskell または OCaml に由来するため、それらは既に存在しており、翻訳する必要はありません。

つまり、新しい機能を追加するために必要な複雑なコードは、Haskell の 1 つの場所に追加するだけで済みます。その後、複数の場所で非常に簡単に使用できますが、多くの場合、多くの「ノイズ」を追加する必要があります。 Haskell 機能をエミュレートする場合は Scala コード。

于 2012-08-21T14:47:55.497 に答える
5

Haskell では、Scala の継承とサブタイプではなく、修飾された型と合計型を使用することを推奨していますが、Haskell で Scala の設計を模倣できます。Scala に関する私の限られた知識から抜け出して、以下の Haskell で同じことを書きました。

  • 特性はクラスです
  • ケースクラスはADTです
  • 特性の継承はクラス メンバーシップです
  • 特性型のメンバーは境界付きの存在型です
  • クラスTypeableはダウンキャストに使用されます
-- Define traits
class Typeable a => Sql a
class (Typeable a, Sql a) => Statement a
class (Typeable a, Sql a) => Where a

-- Define case classes
data Union  where Union     :: (Statement a, Statement b) => a -> b -> Union deriving (Typeable)
data Select where Select    :: Where a => a -> Select                        deriving (Typeable)          

data And    where And       :: (Where a, Where b) => a -> b -> And           deriving (Typeable)
data Or     where Or        :: (Where a, Where b) => a -> b -> Or            deriving (Typeable)
data Equals where Equals    :: Equals                                        deriving (Typeable)

-- Define subtyping
instance Sql Union
instance Statement Union
instance Sql Select
instance Statement Select
instance Sql And
instance Where And
instance Sql Or
instance Where Or
instance Sql Equals
instance Where Equals

StatementHaskell では、 andWhereクラスの代わりに sum 型を使用するでしょう。

class Sql a
instance Sql Statement
instance Sql Where

data Statement = Union Statement Statement | Select Where
data Where = And Where Where | Or Where Where | Equals
于 2012-08-21T14:55:05.063 に答える