0

関数のポリモーフィズムについて読み、この例を見ました

 fun len nil = 0
   | len rest = 1 + len (tl rest)

nil他のすべての例も argを扱っています。

次のような他のタイプのポリモーフィズムの概念を確認したかった

fun func (a : int) : int = 1  
  | func (b : string) : int = 2  ;

フォローエラーが発生しました

stdIn:1.6-2.33 Error: parameter or result constraints of clauses don't agree 
[tycon mismatch]
  this clause:      string -> int
  previous clauses:      int -> int
  in declaration:
    func = (fn a : int => 1: int
             | b : string => 2: int)

上記の関数の間違いは何ですか?それはまったく合法ですか?

4

2 に答える 2

2

サブタイプ多型:

Java、C#、C++ などのプログラミング言語では、ポリモーフィズムを管理する一連のサブタイプ規則があります。たとえば、オブジェクト指向プログラミング言語で、型 B のスーパータイプである型 A がある場合。では、A が表示されている場所ならどこでも B を渡すことができますよね?

たとえば、タイプ Mammal があり、Dog と Cat が Mammal のサブタイプである場合、Mammal が表示される場所ならどこでも、Dog または Cat を渡すことができます。

データ型とコンストラクターを使用して、SML で同じ概念を実現できます。例えば:

datatype mammal = Dog of String | Cat of String

次に、次のような哺乳類を受け取る関数がある場合:

fun walk(m: mammal) = ...

次に、哺乳類のコンストラクタであるため、Dog または Cat を渡すことができます。例えば:

walk(Dog("Fido"));
walk(Cat("Zoe"));

これが、オブジェクト指向言語でサブタイプ ポリモーフィズムとして知られているものに似たものを SML が実現する方法です。

アドホック ポリモーフィズム:

強要

混乱の実際のポイントは、Java、C#、および C++ などの言語には通常、型の自動強制変換があるという事実です。たとえば、Java では、intをlongに、floatdoubleに自動的に強制変換できます。そのため、double を受け入れる関数を作成し、整数を渡すことができます。これらの自動強制をアドホック ポリモーフィズムと呼ぶ人もいます。

このようなポリモーフィズムは SML には存在しません。そのような場合、手動で強制するか、あるタイプを別のタイプに変換する必要があります。

fun calc(r: real) = r

整数で呼び出すことはできません。そのためには、最初に変換する必要があります。

calc(Real.fromInt(10));

ご覧のとおり、SML にはこの種のアドホックなポリモーフィズムはありません。キャスト/変換/強制を手動で行う必要があります。

関数のオーバーロード

アドホック ポリモーフィズムのもう 1 つの形式は、Java、C#、C++ などの言語でメソッドのオーバーロードと呼ばれるものです。繰り返しますが、SML にはそのようなものはありません。2 つの異なる関数を異なる名前で定義することはできますが、同じ関数 (同じ名前) が異なるパラメーターまたはパラメーター タイプを受け取ることはできません。

この関数またはメソッドのオーバーロードの概念を、例で使用しているものと混同してはなりません。これは、単に関数のパターン マッチングです。これは、次のようなもののシンタンティック シュガーです。

fun len xs =
  if null xs then 0
  else 1 + len(tl xs)

パラメトリック ポリモーフィズム:

最後に、SML はパラメトリック ポリモーフィズムを提供します。これは、ジェネリックが Java や C# で行うものと非常によく似ており、C++ のテンプレートにいくらか似ていることを理解しています。

したがって、たとえば、次のようなタイプを持つことができます

datatype 'a list = Empty | Cons of 'a * 'a list

このような型では、'a は任意の型を表します。したがって、これはポリモーフィック型です。そのため、同じ型を使用して整数のリストまたは文字列のリストを定義できます。

val listOfString = Cons("Obi-wan", Empty);

または整数のリスト

val numbers = Cons(1, Empty);

または哺乳類のリスト:

val pets = Cons(Cat("Milo", Cons(Dog("Bentley"), Empty)));

これは、パラメトリック ポリモーフィズムを持つ SML リストでも同じことができます。

多くの「異なるタイプ」のリストを定義できます。

val listOfString = "Yoda"::"Anakin"::"Luke"::[]
val listOfIntegers 1::2::3::4::[]
val listOfMammals = Cat("Misingo")::Dog("Fido")::Cat("Dexter")::Dog("Tank")::[]

同じ意味で、恒等関数がある次の例のように、関数にパラメトリック ポリモーフィズムを含めることができます。

fun id x = x

x の型は 'a です。これは基本的に、次のように任意の型に置き換えることができることを意味します。

id("hello");
id(35);
id(Dog("Diesel"));
id(Cat("Milo"));

ご覧のとおり、これらのさまざまな形式のポリモーフィズムをすべて組み合わせることで、他の静的型付け言語で行うのと同じことを実現できるはずです。

于 2013-02-26T16:01:48.053 に答える
1

いいえ、合法ではありません。SML では、すべての関数に型があります。len例として挙げた関数の型は

fn : 'a list -> int

つまり、任意の型のリストを取り、整数を返します。あなたが作成しようとしている関数は、整数または文字列を取り、整数を返しますが、これは SML 型システムでは正しくありません。通常の回避策は、ラッパー タイプを作成することです。

datatype wrapper = I of int | S of string

fun func (I a) = 1
  | func (S a) = 2

その関数には型があります

fn : wrapper -> int

wherewrapperには、整数または文字列を含めることができます。

于 2013-02-26T14:08:25.143 に答える