2012-03-15 14 views
1

標準のMLで、2つのパラメータを取り、boolを返す関数を作成しようとしています.2つのパラメータは、仕様では'a * 'a -> boolと書かれていますが、試してみると2つのパラメータ自動的にints。どのようにして関数に2つのパラメータ 'a'を取らせることができますか?標準MLでは、どのようにして 'a *' a - > bool型の関数を定義できますか?

次関数アイブが実装しようとしている。

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

しかし、私は何を得る上記の関数を書いた後である:

val lessThan = fn : int * int -> bool 

と私は何をしたいが、このです:

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

私はそれを動作させるために何ができますか?

答えて

6

標準MLには、関数が終了して値を返すようにするには、タイプが'a * 'a -> boolの2つの関数しかありません。それらはすべて上記の2つのものと区別できない、そのタイプの他のすべての純粋な関数があります。

これら2つの機能は、実際にはより一般的なタイプ'a * 'b -> boolです。

これは実際にプログラミング言語理論からかなり深い結果です。基礎を学びたいと思えば、ジョン・レイノルズの表現主義独立やフィル・ワドラーの「自由定理」の研究を読むことができます。

+1

良いコメントと(明らかに)美しい論文ですが、OPの質問では、問題はオペレータがintでのみ定義されていることと関連があります。 (この反応が何らかの考え方にも合致しないとは言いませんが、確かにそうです!) –

+1

ところで、あなたがそれを言いました(@aizen)、Ramsey博士の論文は "Theorems for free"誰にでも本当に素晴らしい読書! –

0

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

たとえば、質問(あなたの意味よりも低い)であなたの機能を定義するTOTALORDERという署名が存在するとします。

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

あなたは関数がelement * element -> boolとして定義され、要素の型が、ここで定義されていない見ることができるように。

次のように私たちは、その後、さまざまなタイプで動作するようにTOTALORDERの二つの異なる実装を定義することができます。私たちの上

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つの機能で署名を定義していることがわかりますが定義。ファンクタは、そのようなシグネチャの実装をパラメータとして受け取ります。後で、それを使用して、strucの実装で、ペアを昇順または降順にソートします。

最終的に、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のような他の言語に比べて、確かに冗長だが、私はそれが問題を解決するための有効なアプローチだと考えています。

関連する問題