1

標準 ML で 2 つのパラメーターを取り、bool を返す関数を作成しようとしています。2 つのパラメーターは仕様で任意の型にすることができますが、'a * 'a -> bool試してみると、2 つのパラメーターが自動的に int になります。関数がタイプ 'aの2つのパラメーターを取るようにするにはどうすればよいですか。

以下は、実装しようとしている関数です。

fun lessThan (a, b) = 
    if a < b then true
    else false;

しかし、上記の関数を書いた後、私が得るものは次のとおりです:

val lessThan = fn : int * int -> bool

そして私が欲しいのはこれです:

val lessThan = fn : 'a * 'a -> bool

機能させるにはどうすればよいですか?

4

2 に答える 2

6

関数が終了して値を返すようにする場合、標準 ML には型の関数が 2 つしかありません'a * 'a -> bool。彼らです

fun ktrue  (_, _) = true
fun kfalse (_, _) = false

そのタイプの他のすべての全純関数は、上記の 2 つと区別できません。

そして、これらの 2 つの関数は、実際にはより一般的な type を持っています'a * 'b -> bool

これは実際には、プログラミング言語理論からのかなり深い結果です。基礎を学びたい場合は、John Reynolds の表現独立に関する研究や Phil Wadler の「自由定理」に関する研究を読んでみてください。

于 2012-03-17T01:54:26.077 に答える
0

これは、SML のファンクターで解決できる種類の問題だと思います。

たとえば、質問で関数を定義する TOTALORDER という署名の存在を考えてみましょう (lt はより低いことを意味します)。

signature TOTALORDER = 
sig
    type element
    val lt: element * element -> bool
end

ご覧のとおり、関数は として定義されておりelement * element -> bool、要素の型はここでは定義されていません。

次に、次のように、TOTALORDER の 2 つの異なる実装を定義して、異なる型で動作するようにします。

structure String : TOTALORDER =
struct
    type element = string
    fun lt(a:string, b) = a < b
end

structure Integer: TOTALORDER = 
struct
    type element = int
    fun lt(a, b) = a < b
end

上記で、文字列を操作できる実装と、整数を操作できる別の実装を定義しました。これらの実装では、 の実際の型を定義していることがわかりますelement

これで、次のように、ファンクターで交換可能な型の魔法を定義できます。

functor MakeComparator(Lt: TOTALORDER):
    sig
        val descending : Lt.element * Lt.element -> Lt.element * Lt.element
        val ascending : Lt.element * Lt.element -> Lt.element * Lt.element
    end
    =
    struct
        open Lt;

        fun descending(a,b) = if lt(a,b) then (b,a) else (a,b)
        fun ascending(a,b) = if lt(a,b) then (a,b) else (b,a)
    end

ここで、TOTALORDER 定義に基づいて、ファンクターが、昇順と降順という 2 つの関数でシグネチャを定義していることがわかります。ファンクターは、そのような署名の実装をパラメーターとして受け取ります。その後、構造体の実装でそれを使用して、ペアを昇順または降順でソートします。

したがって、最終的には、a と b の型は、ファンクターに提供される TOTALORDER の実装における要素の型に依存します。

次のように、さまざまな比較タイプを使用してさまざまな実装を作成できるようになりました。

structure StringComparator = MakeComparator(String)
structure IntegerComparator = MakeComparator(Integer)

そして、それらの型に応じてそれらを使用できます。例えば:

val res01 = StringComparator.ascending("arm","house") (*(arm,house)*)
val res02 = StringComparator.descending("arm","house") (*(house,arm)*)
val res03 = IntegerComparator.ascending(1,2) (*(1,2)*)
val res04 = IntegerComparator.descending(1,2) (*(2,1)*)

型クラスを持つ Haskell のような他の言語と比較すると、確かに冗長ですが、問題を解決するための有効なアプローチだと思います。

于 2013-04-22T16:08:17.403 に答える